《Effective C++》学习笔记——条款37
来源:互联网 发布:按键精灵 查询数据库 编辑:程序博客网 时间:2024/06/05 21:11
六、继承与面向对象设计
条款37、绝不重新定义继承而来的缺省参数值
- 本条款主要讨论:继承一个带有缺省参数的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;
现在,Rectangle类 与 Circle类 都继承自 Shape类。
ps、pc、pr 在声明时,是指向Shape的指针,所以,静态类型都是 Shape*
但 pc、pr 指向了两个类,所以它们动态类型分别为 Circle* 与 Rectangle* (ps未指向任何对象,所以没有动态类型)
pc->draw(ShapeColor::Red);pr->draw(ShapeColor::Red);
分别相当于调用:
Circle::draw(ShapeColor::Red)Rectangle::draw(ShapeColor::Red)
但,如果是
pr->draw();
理论上来讲,pr的动态类型是Rectangle* ,所以应该是 Rectangle::draw(ShapeColor::Green), 但由于 pr 的静态类型是Shape*, 它缺省参数值来自Shape class,也就是 ShapeColor::Red。
原因 与 错误的方法
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; ...};
—— 代码重复,而且不易修改维护
替换它, NVI手法
当然,对于这种需求,也非束手无策。
既然这条路行不通,那我们换条路,用别的替代它。
在条款35中就有许多替代方法,这里讲述 NVI手法
让基类的public non-virtual函数 调用 private virtual函数,让 non-virtual函数负责指定缺省参数值,virtual函数负责实现具体的东西。
class Shape {public: enum ShapeColor { Red, Green, Blue }; void draw(ShapeColor 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; ...};
因为 non-virtual函数 绝对不应该被重定义(根据条款36),所以draw函数的 color缺省值,应该永远为ShapeColor::Red
请记住
- 绝对不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而virtual函数(唯一应该被重定义的东西)是动态绑定。
注释:
- ①. 这样定义以后,如果用户通过对象调用此函数,一定要指定参数值。因为,静态绑定下这个函数并不会继承基类的缺省参数值。但如果通过指针(或引用)来调用这个函数,就可以不指定参数值,因为动态绑定下这个函数会继承基类的缺省参数值。
0 0
- 《Effective C++》学习笔记——条款37
- 《Effective C++》学习笔记——条款15
- 《Effective C++》学习笔记——条款16
- 《Effective C++》学习笔记——条款17
- 《Effective C++》学习笔记——条款18
- 《Effective C++》学习笔记——条款19
- 《Effective C++》学习笔记——条款20
- 《Effective C++》学习笔记——条款21
- 《Effective C++》学习笔记——条款22
- 《Effective C++》学习笔记——条款23
- 《Effective C++》学习笔记——条款24
- 《Effective C++》学习笔记——条款25
- 《Effective C++》学习笔记——条款26
- 《Effective C++》学习笔记——条款27
- 《Effective C++》学习笔记——条款28
- 《Effective C++》学习笔记——条款29
- 《Effective C++》学习笔记——条款30
- 《Effective C++》学习笔记——条款31
- php可变参数
- android开源框架之PullToRefresh概述
- libcurl库进行http通讯-一些基本的函数
- 错排公式
- 单点登录cas常见问题(十) - 怎么将认证方式改为JDBC方式?
- 《Effective C++》学习笔记——条款37
- 学习网络的一些链接
- 一句话解释编程语言
- Java开发中的23种设计模式详解
- PCA数学原理
- 【CSS3】 CSS3实现“图片阴影”效果
- 你所不知的 CSS ::before 和 ::after 伪元素用法
- vim简单配置(cp:http://www.linuxidc.com/Linux/2014-02/96396.htm)
- Character