首页 > 试题广场 >

以下程序输出结果是____。

[单选题]
以下程序输出结果是____。
class A
{
public:
    virtual void func(int val = 1)
    { std::cout<<"A->"<<val <<std::endl;}
    virtual void test()
    { func();}
};
class B : public A
{
public:
    void func(int val=0)
{std::cout<<"B->"<<val <<std::endl;}
};
int main(int argc ,char* argv[])
{
    B*p = new B;
    p->test();
return 0;
}

  • A->0
  • B->1
  • A->1
  • B->0
  • 编译出错
  • 以上都不对
推荐
B
缺省参数是静态绑定的,对于这个特性,估计没有人会喜欢。所以,永远记住:
“绝不重新定义继承而来的缺省参数(Never redefine function’s inherited default parameters v
“绝不重新定义继承而来的缺省参数(Never redefine function’s inherited default parameters v alue.)”
编辑于 2015-12-12 11:28:46 回复(6)
正确答案:B
记住:virtual 函数是动态绑定,而缺省参数值却是静态绑定。 意思是你可能会 在“调用一个定义于派生类内的virtual函数”的同时,却使用基类为它所指定的缺省参数值。
结论:绝不重新定义继承而来的缺省参数值!(可参考《Effective C++》条款37
对于本例:
B*p = newB;
p->test();
p->test()执行过程理解
       (1) 由于B类中没有覆盖(重写)基类中的虚函数test(),因此会调用基类A中的test()
       (2) A中test()函数中继续调用虚函数 fun(),因为虚函数执行动态绑定,p此时的动态类型(即目前所指对象的类型)为B*,因此此时调用虚函数fun()时,执行的是B类中的fun();所以先输出“B->”;
       (3) 缺省参数值是静态绑定,即此时val的值使用的是基类A中的缺省参数值,其值在编译阶段已经绑定,值为1,所以输出“1”;
       最终输出“B->1”。所以大家还是记住上述结论:绝不重新定义继承而来的缺省参数值!
发表于 2016-08-26 11:43:49 回复(14)

如果你真的懂这题的话,你应该知道这些

#include <iostream>
using namespace std;
class A
{
public:
    virtual void func(int val = 1)
    {
        std::cout " << val << std::endl;
    }
    virtual void test()
    {
        func();
    }
};
class B : public A
{
public:
    void func(int val = 0)
    {
        std::cout " << val << std::endl;
    }
};
int main(int argc, char* argv[])
{
    A*p1 = new A;
    A*p2 = new B;
    //B*p3 = new A;    //error
    B*p3 =  reinterpret_cast<B*> (new A);
    B*p4 = new B;
    //测试test()
    p1->test();    //A->1
    p2->test();    //B->1
    p3->test();    //A->1
    p4->test();    //B->1
    //测试func()
    p1->func();    //A->1
    p2->func();    //B->1
    p3->func();    //A->0
    p4->func();    //B->0
    return 0;
}

当然还有其他的玩法:
去掉virtual版

#include <iostream>
using namespace std;
class A
{
public:
    void func(int val = 1)
    {
        std::cout " << val << std::endl;
    }
    //这个test()的virtual可有可无
    virtual void test()
    {
        func();
    }
};
class B : public A
{
public:
    void func(int val = 0)
    {
        std::cout " << val << std::endl;
    }
};
int main(int argc, char* argv[])
{
    A*p1 = new A;
    A*p2 = new B;
    //B*p3 = new A;    //error
    B*p3 = reinterpret_cast<B*> (new A);
    B*p4 = new B;
    //test()
    p1->test();    //A->1
    p2->test();    //A->1
    p3->test();    //A->1
    p4->test();    //A->1
                   //func()
    p1->func();    //A->1
    p2->func();    //A->1
    p3->func();    //B->0
    p4->func();    //B->0
    return 0;
}

现在你应该对effect c++条款37了解了吧
以及virtual函数动态联编,缺省参数静态联编,有个全面的认识。

如果这个对你有帮助,请帮忙点赞,让更多牛油看见。

编辑于 2017-09-18 10:31:07 回复(10)
选择B:
程序运行的过程:
B*p = new B;//调用B的构造函数,此时发现继承自A,所以先调A的构造函数,结束后,再调B的构造函数。
 p->test();//调用test()函数,此时需要调用func()函数,因为缺省参数是静态绑定的,“绝不重新定义继承而来的缺省参数,所以打印B->1
发表于 2015-08-29 09:10:54 回复(2)
当虚函数和默认参数一起出现的时候,编译器为了执行效率,编译的时候进行的是静态绑定,也就是class A中的fun,而在真正执行的时候,则是调用class B的fun,但是此时传递的参数就是1咯
发表于 2015-08-26 23:42:55 回复(0)
C++编译器默认参数的静态绑定的结果。
下面我主要说一下为什么编译器要对默认参数进行静态绑定,而不是运行时动态绑定?
首先,编译器如何实现虚函数调用的动态绑定。
通过类的虚函数表和对象的虚表指针。通过对象的虚表指针,可以找到实际的类的虚函数表,从而多态的调用不同的虚函数。这类似于C语言中的函数指针。当函数指针赋予不同的值调用不同的函数。
然而,这种方法并不能作用在默认参数上。在编译阶段,当编译器找到含默认参数的函数调用时,由于这个调用的函数并不在之前的声明中,所以编译器就会去找能够调用的函数,即是含默认参数的函数。而在程序中并没有提供该参数的值,所以编译器自然就会为该参数提供参数栈空间,就是push压栈操作。那么问题来了,压入哪个值才对呢?自然就是默认参数提供的值了。
在编译A::test()函数时,func()的默认参数值自然就是类A的func提供的参数。而如果B中有函数调用func()时,自然默认压入的值就是B中func()提供的参数。
关键问题在于在编译阶段就必须要决定压入哪个默认参数,当然编译器会选择它所知道的默认参数。也就是类内的函数提供的默认参数。
发表于 2015-12-11 14:58:00 回复(0)
http://blog.csdn.net/chgaowei/article/details/6427731
发表于 2015-08-31 09:57:29 回复(0)
  class A
{
public:
    virtual void func(int val = 1)
    { std::cout<<"A->"<<val <<std::endl;}
    virtual void test()
    { func();}
};
class B : public A
{
public:
    void func(int val=0)
    {std::cout<<"B->"<<val <<std::endl;}
};
int main(int argc ,char* argv[])
{
    A *pa=new B;
    B*p = new B;
    
    pa->func();
    p->test();
    p->func();

    return 0;
}

结果为:
B->1
B->1
B->0

编辑于 2015-11-19 21:45:37 回复(1)
virtualvoidtest()
{ func();} //编译器查看A::func,发现缺省值为1,于是把函数调用修改成func(1)
在运行调用时,调用的便是B::func(1),相当于给这个函数传递了一个参数。
所以绝不要调用重新定义继承而来的参数缺省值。
发表于 2016-07-30 15:11:21 回复(0)
绝不重新定义继承而来的缺省参数值

在类B中没有覆盖(重写)基类中的虚函数test(),因此会调用基类A中的test()函数。
 在A类的test()函数中,调用了虚函数func()。由于指针p的动态类型为B*,所以在调用虚函数func()时会执行B类中的func()函数。
 由于在调用test()函数时没有提供参数,所以使用默认参数值1,因此输出结果为"B->1"。
发表于 2023-11-29 20:28:33 回复(0)
缺省参数值是静态绑定 ,即此时val的值 使用的是基类A中的缺省参数值 ,其值在编译阶段已经绑定,值为1,所以输出“1 ”;
       最终输出“B->1”。所以大家还是记住上述结论:绝不重新定义继承而来的缺省参数值!
发表于 2017-06-26 22:59:31 回复(0)
http://www.oschina.net/question/54100_20313
发表于 2016-07-06 12:54:36 回复(0)
因为缺省参数是静态绑定的,“绝不重新定义继承而来的缺省参数
发表于 2016-02-28 17:53:43 回复(1)
缺省参数是静态绑定的~~!!
发表于 2015-08-31 21:54:06 回复(0)
virtual 函数是动态绑定,而缺省参数值却是静态绑定。绝不重新定义继承而来的缺省参数值!
编辑于 2023-10-24 17:48:56 回复(1)
首先用B类的指针接收的,所以不构成多态;其次A类中有虚函数func且在B类中也有func,构成重写。重写时派生类中的重写的函数只是重写函数的内容也就是函数体{}中的内容,参数列表中的内容还是父类中的func参数列表的内容,所以调用test时,B类中继承了A类的test,test调用B类中重写的函数func,参数中的缺省值没有重写,仍然是1,所以结果是B->1
发表于 2025-01-12 16:28:03 回复(0)
绝不重新定义继承而来的缺省参数值!!!!!!!!
发表于 2020-08-26 15:00:10 回复(0)
1.缺省参数为静态绑定
2.绝不重新定义继承而来的缺省参数
3.静态绑定和动态绑定的区别
发表于 2020-06-25 09:32:13 回复(0)
执行完B*p=new B;下一行执行完进入class的test执行func,进入class B的func但是val为1
发表于 2019-10-10 21:51:40 回复(0)
q11头像 q11
这篇博客对虚函数的介绍写的比较清晰。
编辑于 2019-07-10 09:59:40 回复(0)
这东西。。。,主要靠天赋,我说完了
发表于 2019-07-04 11:40:52 回复(0)