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

本文探讨了为何不能重新定义继承自基类的virtual函数的缺省参数值,强调了静态绑定与动态绑定的区别,并解释了C++这样设计的原因是为了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

Never redefine a function’s inherited default parameter value

我们在条款36刚刚说过继承non-virtual函数是错误的。所以本条款更确切的说是:绝不重新定义继承而来的带有缺省参数值的virtual函数。理由很明确:virtual是动态绑定,而缺省参数是静态绑定

动态绑定又叫后期绑定,静态绑定又叫前期绑定。我们来复习一下两者区别吧:

我们先说一下静态类型和动态类型的概念:对象的所谓静态类型就是它在程序中被声明时所采用的类型对象的动态类型指的是目前所指对象的类型,也就是说动态类型可以表现出一个对象将会有什么行为

通过代码说事儿吧:

//一个描述几何形状的class
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;
    //用户以对象调用时必须指定参数
    //因为静态绑定下,这个函数并不从base继承缺省参数值
    //用户以引用调用时可以不指定参数
    //因为动态绑定下,这个函数会从base继承缺省参数值
}

Shape* ps;				//静态类型为Shape*,没有动态类型
Shape* pc=new Circle;	//静态类型为Shape*,动态类型为Circle*
Shape* pr=new Rectangle;//静态类型为Shape*,动态类型为Rectangle*
//注意上述三个指针,不论他们真正指向什么,他们的静态类型都不会变
//动态类型则可以在程序执行过程中改变(通常是赋值引起)

//virtual函数是动态绑定,也就是说调用一个virtual函数时,
//究竟调用哪一份函数实现代码,取决于发出调用的那个对象的动态类型.
pc->draw(Shape::Red);//调用Circle::draw
pr->draw(Shape::Red);//调用Rectangle::draw

//我们来看下面的问题
pr->draw();//调用Rectangle::draw
//这里pr的动态类型是Rectangle,所以调用Rectangle::draw,
//而函数的缺省值应该是Green
//但是由于pr的静态类型是Shape*,所以缺省参数值来自Shape
//结果是你的代码出现二义性了

//为什么C++以这种奇怪的方式来运作呢?
//因为效率,如果缺省函数是动态绑定,那么编译器就必须提供某种让运行期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=Red)const;
    ...
};
//这更糟糕,代码重复了。。。
//更糟糕的是Shape给的缺省值一旦改变,所以派生类的该virtual function都要跟着变


请记住

绝不重新定义继承而来的缺省参数值,因为缺省参数是静态绑定,而virtual函数(你唯一应该覆写的东西)是动态绑定,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值