C++虚继承的古怪行为
来源:互联网 发布:java时间字符串转整形 编辑:程序博客网 时间:2024/05/22 13:14
在使用菱形继承的时候,虚继承是一种非常管用的办法,可以避免从同一个祖先继承来两份数据。但是从实践看来,虚继承并不仅仅是这一点区别于普通的继承。
虚继承对基类的构造函数的调用和一般的继承是不一样的,而且这种问题相当难发现。我们可以看看下边这个例子:
这个例子看起来很正常,除了所有的构造函数都带有一个参数以外。当然这也没什么稀奇的,如果确实有这样的需求的话。
但是,这样的code甚至不能编译通过,会报告Grandson没有缺省的构造函数Base::Base能够调用,除非你的Base类有一个无参数的构造函数。但坑爹的是,万一你有这样一个构造函数,就真的麻烦大了。GrandSon(int i)会自己调用Base(),而不是通过Son(int i)去调用Base(int i)。
如果不使用虚继承,那么这样的code一切正常,一点问题都没有。
随便把一个方法定义成“虚函数”一般不会有什么大问题,只不过是vtable会多占一些内存而已。但是把普通的继承改成虚继承就会遇到大麻烦。
好吧,谁能告诉我,如果我需要菱形继承,还需要调用基类的相应构造函数,难道只能把构造函数写成这样!?
GrandSon(int i) : Base(i), Son(i)
这要是继承关系复杂一点,就太难维护了。
我实在是没有想通为什么虚继承会有这样古怪的行为。这想必应该不是一个疏漏,而是故意为之。但是,其中的原因何在,我们又应该如何理解这种情况?希望有高手答疑解惑。
下面是vs2012的一个console程序,输出结果极度坑爹。
它的运行结果如图1,看code很难想象居然会是这种结果。但如果不用虚继承,它的结果就会如我们所料,如图2.其中的区别仅仅是把那两个virtual.
虚继承对基类的构造函数的调用和一般的继承是不一样的,而且这种问题相当难发现。我们可以看看下边这个例子:
class Base() { Base(int i) } class Son() : virtual public Base { Son(int i) : Base(i) { } } class Grandson() : virtual public Son { GrandSon(int i) : Son(i) { } }
这个例子看起来很正常,除了所有的构造函数都带有一个参数以外。当然这也没什么稀奇的,如果确实有这样的需求的话。
但是,这样的code甚至不能编译通过,会报告Grandson没有缺省的构造函数Base::Base能够调用,除非你的Base类有一个无参数的构造函数。但坑爹的是,万一你有这样一个构造函数,就真的麻烦大了。GrandSon(int i)会自己调用Base(),而不是通过Son(int i)去调用Base(int i)。
如果不使用虚继承,那么这样的code一切正常,一点问题都没有。
随便把一个方法定义成“虚函数”一般不会有什么大问题,只不过是vtable会多占一些内存而已。但是把普通的继承改成虚继承就会遇到大麻烦。
好吧,谁能告诉我,如果我需要菱形继承,还需要调用基类的相应构造函数,难道只能把构造函数写成这样!?
GrandSon(int i) : Base(i), Son(i)
这要是继承关系复杂一点,就太难维护了。
我实在是没有想通为什么虚继承会有这样古怪的行为。这想必应该不是一个疏漏,而是故意为之。但是,其中的原因何在,我们又应该如何理解这种情况?希望有高手答疑解惑。
下面是vs2012的一个console程序,输出结果极度坑爹。
class Base{public: Base(int i) { std::cout << "Base constructor int" << std::endl; } Base() { std::cout << "Base constructor void" << std::endl; }};class Son : virtual public Base{public: Son(int i) : Base(i) { std::cout << "Son constructor int" << std::endl; } Son() : Base() { std::cout << "Son constructor void" << std::endl; }};class Grandson : virtual public Son{public: Grandson(int i) : Son(i) { std::cout << "Grand son constructor" << std::endl; }};int _tmain(int argc, _TCHAR* argv[]){ Grandson someone(1); return 0;}
它的运行结果如图1,看code很难想象居然会是这种结果。但如果不用虚继承,它的结果就会如我们所料,如图2.其中的区别仅仅是把那两个virtual.
图1,虚继承的执行结果
图2,普通继承的执行结果
0 0
- C++虚继承的古怪行为
- JS进阶,解释this古怪行为
- 古怪的CPU问题
- 古怪的ConfigurationManager类
- 古怪的ConfigurationManager类
- 古怪的孩子
- 古怪的错误
- 古怪的ConfigurationManager类
- 一段古怪的逻辑
- 古怪的VARIANT_BOOL类型
- 古怪的ConfigurationManager类
- 古怪的嗜酒者
- 【js】 古怪的 arguments
- bjfu1014 古怪的实验
- COJ1979-古怪的行列式
- CSU1979: 古怪的行列式
- js原型继承中setter的行为
- (C++)继承、菱形继承和虚继承的那些事儿
- 将word中数据分解到多个文本文件中
- ios 横竖屏控制
- Linux Shell syntax error: unexpected end of file
- 中国特色程序员的[钱途]
- 115个Java面试题和答案——终极列表(上)
- C++虚继承的古怪行为
- How to fix GC overhead limit exceeded in Eclipse
- android 获取本机ipv4地址
- nyoj 17 单调递增最长子序列
- Jquery基础(四) JS的Document属性和方法
- Making your own 3D list [定制3D listview]
- OpenGL绘制旋转三角形实例
- Scala Tips
- ACE使用.ini文件读取及写入修改