• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    6年前 (2013-04-11)  C++ |   抢沙发  12 
    文章评分 0 次,平均分 0.0
    #include <iostream>
    using namespace std;
    
    class A{
    public:
    	virtual int fun(int i = 1);
    };
    int A::fun(int i){return i + 1;}
    class B:public A{
    public:
    	virtual int fun(int i = 10);
    };
    int B::fun(int i){return i;}
    int main()
    {
    	A *p = new B();
    	cout << p->fun();
    	delete p;
      return 0;
    };

    上面这段代码输出值是多少?

    或许出乎你的意料为1.我们知道使用基类的指针,可以实现动态绑定,也就算多态。但是函数的默认参数呢,会不会发生动态改变?
    使用p来调用函数func,的确会调用B类的func函数,但是默认参数还是使用基类A的默认参数。

    先说一下现在的C++的参数传递机制,非虚函数和虚函数的传递机制都是一样的。
    比如如下函数调用:
    func(10) ;
    会被编译器翻译成:
    push 10
    push 返回地址
    call func
    大概就是这样:先把参数压栈,然后压返回地址,在调用函数。
    对于虚函数来说,如果调用时没有指定参数值,那么编译器会帮我们加上去。
    这里就有问题来了,如果是用基类指针调用的虚函数,我们知道,因为动态绑定,编译器暂时无法知道实际调用的是哪个函数,此指针操作在实际的类地址中找到虚函数表,再根据偏移找到实际的函数跳转地址,而此时,编译器必须提前把参数压栈准备好,call之后就直接用参数了。
    那么,既然编译器还不知道实际调用的是哪个函数,那么当然就更不知道实际传递的默认参数应该是子类还是父类的了。关键就在这里。
    参数都是静态绑定的,如果要动态,效率会跟虚函数调用一样稍微有点低,所以C++折中了。

    可以参考effective c++中的内容。

     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/552.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享