C++之绝不重新定义继承而来的缺省参数值(37)---《Effective C++》

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

首先让我们进行分析,类的继承中只能继承两种函数,virtual和non-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;
ps=pc;//ps的动态类型为Circle*
ps=pr;//ps的动态类型为Rectangle*
ps->draw(Shape::Red);
ps->draw(Shape::Red);

运行期间动态绑定,非常方便,那么此时还会有什么问题呢?

pr->draw();//调用Rectangle::draw(Shape::Red);

我们明明调用了Rectangle::draw函数,在子类中我们给的参数尚未Shape::Green,然而当我们使用默认实参的时候,却是Shape::Red,为什么呢?
这个问题的答案在于

virtual函数是动态绑定,然鹅缺省参数值却是静态绑定的。。。

这就有些尴尬了,那么这样即使我们重新定义了父类的缺省实参值没有任何用吧。。。,那么C++的设计人员为什么要保留这种大坑呢???答案在于运行期效率,如果缺省参数值是动态绑定,编译器就必须有某种方法在运行期间为virtual函数决定适当的参数缺省值,这笔目前实行的“在编译器决定”的机制更慢而且更加复杂,为了提高程序运行速度同时降低程序复杂性,C++设计人员权衡再三保留了这种坑,然后也告诉了我们避免踩入这个坑的方法——–绝不重新定义继承而来的缺省参数值

当你想令virtual函数表现出你所想要的行为但却遭遇麻烦,聪明的做法是考虑替代设计,条款35中裂了不少virtual函数的替代设计,其中之一是NVI手法,我们咋这个也可也可以使用这种方法,代码如下:

class Shape{
public:
    enum ShapeColor{Red,Green,Blue};
    void draw(Shape Color=Red) const{
        doDraw(color);
    }
    ...
private:
    virtual void doDraw(ShapeColor color) const=0;
};
class Rectangle:public Shape{
public:
    ...
private:
    virtual void doDraw(ShapeColor color) const;
    ...
};

总结:
绝对不要重新定义一个继承而来的缺省实参数值,因为缺省参数值都是静态绑定,而virtual函数—你唯一应该撰写的东西—确实动态绑定!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值