重新定义继承而来的缺省参数值导致的问题
来源:互联网 发布:923字刷爆朋友圈 知乎 编辑:程序博客网 时间:2024/06/05 19:47
不要重新定义继承而来的缺省参数值,这样会导致与你预期的行为不同,《Effective c++》一书中的条款37也对该问题有所讲述。
那么会出现什么问题呢?看如下代码:
#include <iostream>class Base{public: virtual void Show(int n = 10)const{ //提供缺省参数值 std::cout << "Base:" << n << std::endl; }};class Base1 : public Base{public: virtual void Show(int n)const{ std::cout << "Base1:" << n << std::endl; }};int main(){ Base* p1 = new Base1; p1->Show(5); //#1 p1->Show(); //#2 return 0;}输出:
Base1:5Base1:10#1 语句 因多态特性 调用的是Base1::Show 将5作为参数 输出Base1:5 没问题
#2 语句 没有提供实参 则使用从基类继承而来的缺省参数值10 输出Base1:10 也没问题
但是当派生类继承了Show函数后也重新定义了缺省参数值 将会导致问题,看如下代码:
#include <iostream>class Base{public: virtual void Show(int n = 10)const{ //提供缺省参数值 std::cout << "Base:" << n << std::endl; }};class Base1 : public Base{public: virtual void Show(int n = 20)const{ //重新定义继承而来的缺省参数值 std::cout << "Base1:" << n << std::endl; }};int main(){ Base* p1 = new Base1; p1->Show(5); //#1 p1->Show(); //#2 return 0;}到了这里 可能会有同学说 这跟上面差不多啊 #1语句还是输出Base1:5 #2语句因没有提供实参则使用重新定义的缺省参数值啊(Base1:20)但是实际上输出结果是:
Base1:5Base1:10这里 可能就有同学疑惑了,不应该用重新定义的缺省值吗?为什么还是用的基类提供的缺省值?这是因为缺省参数值是静态绑定的 而虚函数是动态绑定的。
上面代码中Base* p1 = new Base1;中p1是指向Base的指针 是静态类型,动态类型就是Base1*。
而虚函数是通过动态绑定而来,意思是调用哪个版本的虚函数,取决于发出调用的那个对象的动态类型,这里动态类型是Base1*,所以调用该类版本的虚函数,但是缺省参数值是静态绑定,也就是当没有提供参数的时候,使用哪个虚函数版本提供的缺省参数值是由静态类型决定的 ,这里也就是Base版本的提供的缺省值。所以#2使用的是Base版本的缺省值而不是Base1的版本的缺省值。
到这里 可能还是有同学不是很明白,不要紧,那么再看如下代码,可能会清楚很多。
#include <iostream>class Base{public: virtual void Show(int n = 10)const{ //提供缺省参数值 std::cout << "Base:" << n << std::endl; }};class Base1 : public Base{public: virtual void Show(int n = 20)const{ //重新定义缺省值 std::cout << "Base1:" << n << std::endl; }};class Base2 : public Base1{public: virtual void Show(int n = 50)const{ //重新定义缺省值 std::cout << "Base2:" << n << std::endl; }};int main(){ Base* p1 = new Base1; p1->Show(5); //#1 p1->Show(); //#2 Base* p2 = new Base2; //静态类型p2(Base*) 动态类型(Base2*) p2->Show(); //#3 Base1* p3 = new Base1; //静态类型p3(Base1*) 动态类型(Base1*) p3->Show(); //#4 Base1* p4 = new Base2; //静态类型p4(Base1*) 动态类型(Base2*) p4->Show(); //#5 Base2* p5 = new Base2; //静态类型p5(Base2*) 动态类型(Base2) p5->Show(); //#6 return 0;}以上代码有一个继承体系:Base)Base1)Base2
#3调用动态类型版本的虚函数Base2::Show,然后使用静态类型提供的缺省值(10)
#4 #5 #6 都是一样的 调用动态类型版本的虚函数 然后使用静态类型提供的缺省值
所以最终输出结果:
Base1:5Base1:10Base2:10Base1:20Base2:20Base2:50另外不仅仅是通过指针调用会出现这种问题 通过引用调用也会有这种问题 所以不要重新定义继承而来的缺省参数值 因为这样不会有你所希望的执行结果。有人可能会问了 通过对象而不是指针或引用调用“虚函数”不会出现如上问题啊。是啊,的确不会出现如上问题,但是你通过对象调用的话,就同时失去了多态性,因为对象调用,是直接调用的该对象版本的“虚函数” 这样虚函数就没有什么意义了。既然定义虚函数,就可能会使用多态特性,使用多态特性就可能会出现如上问题。
阅读全文
0 0
- 重新定义继承而来的缺省参数值导致的问题
- 绝不重新定义继承而来的缺省参数值
- 绝不重新定义继承而来的缺省参数值
- 绝不重新定义继承而来的缺省参数值
- 不重新定义继承而来的缺省参数值
- 不要重新定义继承而来的缺省参数值
- 不要重新定义继承而来的缺省参数值
- 绝对不要重新定义继承而来的缺省参数
- 绝不重新定义继承而来的函数的缺省参数值
- 《Effective C++》37: 绝不重新定义继承而来的缺省的参数值
- 决不要重新定义继承而来的缺省参数值
- 决不要重新定义继承而来的缺省参数值
- 条款37:绝不重新定义继承而来的缺省参数值
- 条款37:绝不重新定义继承而来的缺省参数值
- 条款37:绝不重新定义继承而来的缺省参数值
- effective c++ 条款38: 决不要重新定义继承而来的缺省参数值
- 决不要重新定义继承而来的缺省参数值
- 决不要重新定义继承而来的缺省参数值
- Cyber security和Network security的区别
- 每日一得20171010
- 最短路 (dijkstra )
- andrid 使用handler制作的定时器例子
- 常用8个搜索技巧
- 重新定义继承而来的缺省参数值导致的问题
- POJ 1144 Network 求割点
- Java NIO 详解
- bzoj1411
- 在一个普通的html文件中引入es6
- 判断 SharedPreferences 是否是第一次登录
- mysql、oracle、sqlserver根据对应的表查询表中的所有字段名称、类型、别名、长度等信息
- TensorFlow中CNN的两种padding方式“SAME”和“VALID”
- Spring使用Cache、整合Ehcache