虚基类
来源:互联网 发布:布吉岛漫画软件 编辑:程序博客网 时间:2024/06/16 17:52
一、虚基类的作用:
当一个基类被声明为虚基类后,即使它成为了多继承链路上的公共基类,最后的派生类中也只有它的一个备份。
二、虚基类的特点:
虚基类构造函数的参数必须由最新派生出来的类负责初始化(即使不是直接继承);
虚基类的构造函数先于非虚基类的构造函数执行。
三、RTTI、虚函数和虚基类的开销分析:
详细分析见http://baiy.cn/doc/cpp/inside_rtti.htm。
四、实例分析:
1、无虚函数的虚基类class Base{public:int a;Base(int aa):a(aa){}};class Derived1: virtual public Base{public:int a;Derived1(int aa):Base(aa), a(aa){}};class Derived2: virtual public Base{public:int b;Derived2(int aa):Base(aa), b(aa){}};class SubDerived: public Derived1, public Derived2{public:int a;SubDerived(int a1, int a2, int a3, int a4):Derived1(a2), Derived2(a3), a(a4), Base(a1){}};类的结构如下:1> class Basesize(4):1> +---1> 0| a1> +---1> 1> class Derived1size(12):1> +---1> 0| {vbptr}//虚基类指针1> 4| a1> +---1> +--- (virtual base Base)1> 8| a1> +---1> 1> Derived1::$vbtable@:1> 0| 01> 1| 8 (Derived1d(Derived1+0)Base)1> 1> class Derived2size(12):1> +---1> 0| {vbptr}1> 4| b1> +---1> +--- (virtual base Base)1> 8| a1> +---1> 1> Derived2::$vbtable@:1> 0| 01> 1| 8 (Derived2d(Derived2+0)Base)1> 1> class SubDerivedsize(24):1> +---1> | +--- (base class Derived1)1> 0| | {vbptr}1> 4| | a1> | +---1> | +--- (base class Derived2)1> 8| | {vbptr}1> 12| | b1> | +---1> 16| a //该类自己定义的变量1> +---1> +--- (virtual base Base) //仅有的一份共有Base基类1> 20| a1> +---1> 1> SubDerived::$vbtable@Derived1@:1> 0| 01> 1| 20 (SubDerivedd(Derived1+0)Base)1> 1> SubDerived::$vbtable@Derived2@:1> 0| 01> 1| 12 (SubDerivedd(Derived2+0)Base)2、有虚函数的虚继承class Base{public:Base(int aa, int bb): a(aa), b(bb){fun();}virtual void fun(){cout<<"Base"<<a<<endl;}int a;const int b;};class Derived1: virtual public Base{public:Derived1(int aa, int bb): Base(aa, bb){fun();}void fun(){cout<<"Derived1"<<a<<endl;}virtual void nonvirtualF(){}int c;};class Derived2: virtual public Base{public:Derived2(int aa, int bb): Base(aa, bb){fun();}void new_fun(){cout<<"Derived2"<<a<<endl;}virtual void nonvirtualF(){}int c;};class SubDrived: public Derived1, public Derived2{public:SubDrived(int aa, int bb):Base(aa, bb), Derived1(aa, bb), Derived2(aa, bb){}virtual void SubDrivedF(){}virtual void SubDrivedFF(){}virtual void SubDrivedFFF(){}int d;};类结构如下:1> class Basesize(12):1> +---1> 0| {vfptr}1> 4| a1> 8| b1> +---1> 1> Base::$vftable@:1> | &Base_meta1> | 01> 0| &Base::fun1> 1> class Derived1size(28):1> +---1> 0| {vfptr} //两个虚函数指针,不同于单纯的虚函数继承1> 4| {vbptr}1> 8| c1> +---1> 12| (vtordisp for vbase Base) //vtordisp域Vtordisp(虚基表到类的开始地址的偏移值)的MSDN的解释是:虚继承中派生类重写了基类的虚函数,并且在构造函数或者析构函数中使用指向基类的指针调用了该函数,编译器会为虚基类添加vtordisp域。产生vtordisp字段的条件是:1)派生类重写了虚基类的虚函数;2)派生类定义了构造函数或者析构函数。这两个条件缺一不可。1> +--- (virtual base Base)1> 16| {vfptr}1> 20| a1> 24| b1> +---1> 1> Derived1::$vftable@Derived1@:1> | &Derived1_meta1> | 01> 0| &Derived1::nonvirtualF1> 1> Derived1::$vbtable@:1> 0| -41> 1| 12 (Derived1d(Derived1+4)Base)1> 1> Derived1::$vftable@Base@:1> | -161> 0| &(vtordisp) Derived1::fun //Base::fun被覆盖了1> 1> class Derived2size(24):1> +---1> 0| {vfptr}1> 4| {vbptr}1> 8| c1> +---1> +--- (virtual base Base)1> 12| {vfptr}1> 16| a1> 20| b1> +---1> 1> Derived2::$vftable@Derived2@:1> | &Derived2_meta1> | 01> 0| &Derived2::nonvirtualF1> 1> Derived2::$vbtable@:1> 0| -41> 1| 8 (Derived2d(Derived2+4)Base)1> 1> Derived2::$vftable@Base@:1> | -121> 0| &Base::fun1> 1> class SubDrivedsize(44):1> +---1> | +--- (base class Derived1)1> 0| | {vfptr}1> 4| | {vbptr}1> 8| | c1> | +---1> | +--- (base class Derived2)1> 12| | {vfptr}1> 16| | {vbptr}1> 20| | c1> | +---1> 24| d1> +---1> 28| (vtordisp for vbase Base)1> +--- (virtual base Base)1> 32| {vfptr}1> 36| a1> 40| b1> +---1> 1> SubDrived::$vftable@Derived1@:1> | &SubDrived_meta1> | 01> 0| &Derived1::nonvirtualF1> 1| &SubDrived::SubDrivedF //因为没有虚继承,所以SubDerived类没有单独生成vfptr来1> 2| &SubDrived::SubDrivedFF //存放自己的虚函数,而是和单纯虚函数继承一样,将自己的1> 3| &SubDrived::SubDrivedFFF //虚函数放在该类的第一个继承的类的虚函数表中1> 1> SubDrived::$vftable@Derived2@:1> | -121> 0| &Derived2::nonvirtualF1> 1> SubDrived::$vbtable@Derived1@:1> 0| -41> 1| 28 (SubDrivedd(Derived1+4)Base)1> 1> SubDrived::$vbtable@Derived2@:1> 0| -41> 1| 16 (SubDrivedd(Derived2+4)Base)1> 1> SubDrived::$vftable@Base@:1> | -32
0 0
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 虚基类
- 基于X86的linux启动过程以及/etc/inittab详解
- Webkit模块介绍
- Unity中播放StreamingAssets文件夹下的视频文件(PlayFullScreenMovie)
- Android 实现形态各异的双向侧滑菜单 自定义控件来袭
- 联想完成收购IBM x86服务器业务 总额21亿美元
- 虚基类
- 发现新浪微博的一个bug
- <Android>使用系统时间命名文件夹
- HBase中如何执行Ruby
- 64位程序,利用ADO连接Oracle数据库
- java中 使用ImageMagick处理图片(对图片处理要求比较高的解决方案)
- 对于未来编程的十二种预测
- 奇偶排序
- django Widgets