EffectiveC++学习笔记-条款36|37
来源:互联网 发布:甲骨文 ibm做啥软件 编辑:程序博客网 时间:2024/05/29 12:57
条款36 决不重新定义继承而来的non-virtual函数
条款37 决不重新定义继承而来的缺省参数值
决不重新定义继承而来的non-virtual函数
正常情况下non-virtual的函数就应该是被设计的目的之一就是为了不能让子类重写。
看个简单例子:
class Base{public: oid print() { cout << "Base:Print" << endl; }};class Derived : public Base{public: void print() { cout << "Derived:Print" << endl; }};int main(){ Base* pb = new Base; Base *pd = new Derived; pb->print(); pd->print(); while (1) {} return 0;}//打印结果Base:PrintBase:Print
这应该不是我们想要的结果,如果是non-virtual一定不要重写,需要重写的不要设计成non-virtual。
决不重新定义继承而来的缺省参数值
这个情况出现的次数可能不多,但是有一些需要关注的地方,例如:
//基类class Shape{public: enum ColorType { Red, Blue, Green}; virtual void drawColor(ColorType type = Red) const = 0;};class Rect : public Shape{public: virtual void drawColor(ColorType type = Green) const { cout << "drawColor:" << type << endl; }};class Circle : public Shape{public: virtual void drawColor(ColorType type = Blue) const { cout << "drawColor:" << type << endl; }};int main(){ Shape* rect = new Rect(); Shape* circle = new Circle(); rect->drawColor(); circle->drawColor();}//打印结果 两个子类的打印结果都是 0 也就是ReddrawColor:0drawColor:0
回顾一下虚函数的知识,如果父类中存在有虚函数,那么编译器便会为之生成虚表与虚指针,在程序运行时,根据虚指针的指向,来决定调用哪个虚函数,这称之与动态绑定,与之相对的是静态绑定,静态绑定在编译期就决定了。
实现动态绑定的代价是比较大的,所以编译器在函数参数这部分,并没有采用动态绑定的方式,也就是说,默认的形参是静态绑定的,它是编译期就决定下来了。
rect的静态类型是Shape*,动态类型才是Rect*,类似地,circle的静态类型是Shape*,动态类型是Circle*。这里没有带参数,所以使用的是默认的形参,即为静态的Shape::drawColor()里面的缺省值RED,所以两个问题所在处的输出值都是0(也就是red)。
正因为编译器并没有对形参采用动态绑定,所以如果对继承而来的虚函数使用不同的缺省值,将会给读者带来极大的困惑,试想一下下面两行代码:
Shape *rect = new Rect(); // 默认值是REDRect *rect_temp = new Rect(); // 默认值是GREEN
解决办法
有问题就会有解决方法:
我们可以使用non-virtual调用virtual函数。
//基类class Shape{public: enum ColorType { Red, Blue, Green }; void draw(ColorType type = Red) const //子类不必实现该函数 { drawColor(type); }private: //真正处理工作的地方 virtual void drawColor(ColorType type) const = 0;};class Rect : public Shape{public:private: virtual void drawColor(ColorType type) const { cout << "drawColor:" << type << endl; }};class Circle : public Shape{public:private: virtual void drawColor(ColorType type) const { cout << "drawColor:" << type << endl; }};int main(){ Shape* rect = new Rect(); Shape* circle = new Circle(); rect->draw(); circle->draw(); Rect* rect_temp = new Rect(); rect_temp->draw();}
这样继承得到的子类的默认参数都是Red。
阅读全文
0 0
- EffectiveC++学习笔记-条款36|37
- EffectiveC++学习笔记-条款2
- EffectiveC++学习笔记-条款3
- EffectiveC++学习笔记-条款4
- EffectiveC++学习笔记-条款7
- EffectiveC++学习笔记-条款8
- EffectiveC++学习笔记-条款9
- EffectiveC++学习笔记-条款10
- EffectiveC++学习笔记-条款11
- EffectiveC++学习笔记-条款12
- EffectiveC++学习笔记-条款13
- EffectiveC++学习笔记-条款14
- EffectiveC++学习笔记-条款38
- EffectiveC++学习笔记-条款45
- EffectiveC++学习笔记-条款46
- EffectiveC++学习笔记-条款47
- EffectiveC++学习笔记-条款48
- EffectiveC++学习笔记-条款49
- ssm+maven+angular+bootstrap练习(邮箱页面)--配置文件
- CodeForces 832B Petya and Exam
- 意义的感知和语法的形式,UML类图
- 模拟用户登录功能
- 雨后闲侃儿
- EffectiveC++学习笔记-条款36|37
- ffmpeg中G726解码器用法 编码器用法
- Hongcow Solves A Puzzle CodeForces
- maven3 archetype 汇总
- 02-SpringBoot——Spring基础-Java配置
- 【正一专栏】内马尔留不留下都已经是伤痕累累
- 十四、断路器-Hystrix 对 Feign 的支持
- Bellman-Ford Algorithm
- Oil Deposits ( 简单搜索,连通性)