标签搜索

目 录CONTENT

文章目录

绝不重新定义继承而来的缺省值参数.md

小小城
2021-08-22 / 0 评论 / 0 点赞 / 4 阅读 / 1,186 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-02,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

绝不重新定义继承而来的缺省值参数

@[toc]

一、问题引入

  •  在C++中,只能继承两种函数:虚(virtual)函数和非虚(non-virtual)函数。
  •  而重新定义一个继承而来的带有缺省参数值的虚(virtual)函数永远是错误的
  • 虚(virtual)函数是动态绑定
  • 缺省参数值是静态绑定
class Shape
{
public:
    enum ShapeColor{Red, Green, Blue};
    virtual void draw(ShapeColor color = Red) const = 0;
    ...
};

class Rectangle: public Shape
{
public:
    virtual void draw(ShapeColor color = Green) const;
    ...
};

class Circle: public Shape
{
public:
    virtual void draw(ShapeColor color) const;
    ...
};

以上代码有个问题,如果你用下面的调用方式:

Shape *ps;
Shape *pc = new Circle;
Shape *pr = new Rectangle;

pc->draw(Shape::Red);    //Circle::draw(Shape::Red);
pr->draw(Shape::Red);    //Rectangle::draw(Shape::Red);

pr->draw();          //Rectangle::(Shape::Red)!!!!
  • 我们会发现,pr的动态类型是Rectangle*, 所以调用的是Rectangle的virtual函数,Rectangle::draw的缺省参数应该是GREEN
  • 但是,由于pr的静态类型是Shape*,所以此调用的缺省参数值来自Shape而不是Rectangle。
  • C++之所以这么做,是考虑到运行时效率的问题。如果缺省参数值是动态绑定,编译器就必须在运行期为虚函数决定适当的缺省值。这比目前实行的“在编译器决定”机制更慢更复杂。

二、结论

  •  绝对不要重新定义一个继承而来的缺省参数值,这些参数值都是静态的,而虚函数却是动态的
#include <iostream>      
using namespace std;      
      
class A      
{      
    public:      
    virtual void Print(int a = 999)      
    {      
        cout<<a<<endl;      
    }      
};      
      
class B : public A      
{      
    public:      
    virtual void Print(int a = 666)      
    {      
        cout<<a<<endl;      
    }      
};      
      
void Test(A& a)      
{      
    a.Print();      
}      
      
int main()      
{      
    B b;                                                                                                                                    
    Test(b);      
    return 0; 
}
  • 这段代码的输出结果是999而非666,也就充分验证我们的结论
0

评论区