用代码的角度看C++虚函数、虚继承的影响
2012-09-04 22:07
363 查看
一直以来,c++的虚函数以及虚继承令人讨厌。下面通过程序彻底了解c++的虚函数以及虚继承。
基类中不含虚函数以及不使用虚拟继承时,基类与派生类的size都为1.运行上面的程序,可以看到下面的结果:
继续考虑虚继承对类size的影响。
继承类虚拟继承基类时,继承类的size变成4,这是为什么???
而考虑菱形结构的虚继承的另外一种方式:
继承类虚拟继承基类时,继承类的size变成4,这是为什么???
菱形虚拟继承的常见方式:
继承类虚拟继承基类时,继承类的size变成4,这是为什么???
接着考虑,基类中有虚函数,无虚继承的情况:
前面都是对称的情况,下面考虑一些非对称的情形。例如:基类B1中无虚函数,而B2、B3有虚函数,无虚继承
基类中无虚函数,继承类中有虚函数
B1无虚函数,B2、B3虚继承B1,D继承B2、B3为public
B1有虚函数,B2、B3虚继承B1,并且B2、B3没有虚函数,D继承B2、B3为public,D中没有虚函数
B1含有虚函数,B2和B3虚继承B1,B2和B3也含有虚函数,D公共继承B2和B3,此时D有无虚函数无所谓
B1含有虚函数,B2和B3公共继承B1(此时B2和B3有无虚函数无所谓),D虚拟继承B2、B3,那么D有无虚函数对D有影响
如果D中无虚函数,具体结果如下图
D中无虚函数,各个类的size如左下图
如果D中有虚函数,各个类的size如右上图,具体的类结构见下图:
B2和B3虚拟继承B1(此时B1有无虚函数有影响),D虚拟继承B2、B3,那么B2、B3、D有无虚函数对B2、B3、都有D有影响
若D中没有虚函数,那么D的size为24,即为B2和B3的size之和即不会共享相同的B1中的对象,其他类的size不变。
上面的两个结果为类D中有无成员方法V3()的结果,有V3时D的size为28,没有V3时D的size为24.而在B1、B2、B3中有无非虚成员方法对各个类无影响。
上面的两个结果为类D有虚函数,并且D中有无成员方法V3()的结果,有V3时D的size为28,没有V3时D的size为24.而在B1、B2、B3中有无非虚成员方法对各个类无影响。
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;};//构造函数不能为virtual函数 }; classB2:public B1 { public: B2(){cout<<"B2 constructor"<<endl;};//构造函数不能为virtual函数 void f2(){ cout << "B2::f2" << endl; } }; classB3:public B1 { public: B3(){cout<<"B3 constructor"<<endl;};//构造函数不能为virtual函数 void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;};//构造函数不能为virtual函数 void v3(){ cout << "D::v3" << endl; } }; //======================================= int main (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
基类中不含虚函数以及不使用虚拟继承时,基类与派生类的size都为1.运行上面的程序,可以看到下面的结果:
继续考虑虚继承对类size的影响。
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; }; classB2:publicvirtual B1 { public: B2(){cout<<"B2 constructor"<<endl;}; void f2(){ cout << "B2::f2" << endl; } }; classB3:public virtual B1 { public: B3(){cout<<"B3 constructor"<<endl;}; voidf3(){ cout << "B3::f3"<< endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){cout <<"D::v3" <<endl; } }; //======================================= intmain (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }运行程序,可以看到它的地址表格如下:
继承类虚拟继承基类时,继承类的size变成4,这是为什么???
而考虑菱形结构的虚继承的另外一种方式:
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; }; classB2:public B1 { public: B2(){cout<<"B2 constructor"<<endl;}; void f2(){ cout << "B2::f2" << endl; } }; classB3:public B1 { public: B3(){cout<<"B3 constructor"<<endl;}; voidf3(){ cout << "B3::f3"<< endl; } }; classD :public virtual B2,publicvirtual B3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){cout <<"D::v3" <<endl; } }; //======================================= intmain (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
继承类虚拟继承基类时,继承类的size变成4,这是为什么???
菱形虚拟继承的常见方式:
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; }; classB2:public virtual B1 { public: B2(){cout<<"B2 constructor"<<endl;}; void f2(){ cout << "B2::f2" << endl; } }; classB3:public virtual B1 { public: B3(){cout<<"B3 constructor"<<endl;}; voidf3(){ cout << "B3::f3"<< endl; } }; classD :public virtual B2,publicvirtual B3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){cout <<"D::v3" <<endl; } }; //======================================= intmain (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
继承类虚拟继承基类时,继承类的size变成4,这是为什么???
接着考虑,基类中有虚函数,无虚继承的情况:
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; virtual voidv1(){ cout << "B1::v1"<< endl; } }; classB2:public B1 { public: B2(){cout<<"B2 constructor"<<endl;}; virtualvoid v2(){ cout <<"B2::v2"<< endl; } //如果基类中有虚函数,那么该类中有无虚函数对本类无影响 void f2(){ cout << "B2::f2" << endl; } }; classB3:public B1 { public: //int z; B3(){cout<<"B3 constructor"<<endl;}; virtualvoid v3(){ cout <<"B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; voidv3(){ cout << "D::v3"<< endl; } virtual voidvD(){ cout << "D::vD"<< endl; } }; intmain (int argc,constchar * argv[]) { // insert code here... cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }其结果发生了较大改变:
前面都是对称的情况,下面考虑一些非对称的情形。例如:基类B1中无虚函数,而B2、B3有虚函数,无虚继承
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; //virtual voidv1(){ cout << "B1::v1"<< endl; } }; classB2:public B1 { public: B2(){cout<<"B2 constructor"<<endl;}; virtualvoid v2(){ cout <<"B2::v2"<< endl; } //如果基类中有虚函数,那么该类中有无虚函数对本类无影响 void f2(){ cout << "B2::f2" << endl; } }; classB3:public B1 { public: //int z; B3(){cout<<"B3 constructor"<<endl;}; virtualvoid v3(){ cout <<"B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; voidv3(){ cout << "D::v3"<< endl; } virtual void vD(){ cout << "D::vD"<< endl; } //只要类B2或者B3含有虚函数,该类中有无虚函数无所谓,因为是public继承的原因 }; intmain (int argc,constchar * argv[]) { // insert code here... cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
基类中无虚函数,继承类中有虚函数
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; //virtual voidv1(){ cout << "B1::v1"<< endl; } }; classB2:public B1 { public: B2(){cout<<"B2 constructor"<<endl;}; //virtualvoid v2(){ cout <<"B2::v2"<< endl; } void f2(){ cout << "B2::f2" << endl; } }; classB3:public B1 { public: //int z; B3(){cout<<"B3 constructor"<<endl;}; //virtualvoid v3(){ cout <<"B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; voidv3(){ cout << "D::v3"<< endl; } virtual voidvD(){ cout << "D::vD"<< endl; } }; intmain (int argc,constchar * argv[]) { // insert code here... cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
B1无虚函数,B2、B3虚继承B1,D继承B2、B3为public
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; //virtual void v1(){ cout <<"B1::v1" << endl; } //void f1(){cout << "B1::f1"<< endl; } }; classB2:public virtual B1 { public: B2(){cout<<"B2 constructor"<<endl;}; virtual voidv2(){ cout << "B2::v2"<< endl; } void f2(){ cout << "B2::f2" << endl; } }; classB3:publicvirtualB1 { public: B3(){cout<<"B3 constructor"<<endl;}; virtual voidv3(){ cout << "B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){ cout << "D::v3" << endl; } virtual void vD(){ cout << "D::vD"<< endl;//有无虚函数都是16bytes,因为是公共继承 } }; //======================================= intmain (int argc,constchar * argv[]) { // insert code here... cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
B1有虚函数,B2、B3虚继承B1,并且B2、B3没有虚函数,D继承B2、B3为public,D中没有虚函数
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; virtual voidv1(){cout << "B1::v1"<< endl; } }; classB2:public virtual B1 { public: B2(){cout<<"B2 constructor"<<endl;}; void f2(){ cout << "B2::f2" << endl; } }; classB3:publicvirtualB1 { public: B3(){cout<<"B3 constructor"<<endl;}; void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){ cout << "D::v3" << endl; } }; //======================================= intmain (int argc,constchar * argv[]) { // insert code here... cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
B1含有虚函数,B2和B3虚继承B1,B2和B3也含有虚函数,D公共继承B2和B3,此时D有无虚函数无所谓
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; virtual voidv1(){ cout << "B1::v1"<< endl; } //void f1(){cout << "B1::f1"<< endl; } }; classB2:public virtual B1 { public: //int y; B2(){cout<<"B2 constructor"<<endl;}; virtualvoid v2(){ cout <<"B2::v2"<< endl; } void f2(){ cout << "B2::f2" << endl; } }; classB3:publicvirtualB1 { public: B3(){cout<<"B3 constructor"<<endl;}; virtualvoid v3(){ cout <<"B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :public B2,public B3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){cout <<"D::v3" <<endl; } virtual voidvD(){ cout << "D::vD"<< endl; } }; //======================================= intmain (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
B1含有虚函数,B2和B3公共继承B1(此时B2和B3有无虚函数无所谓),D虚拟继承B2、B3,那么D有无虚函数对D有影响
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; virtual void v1(){ cout << "B1::v1"<< endl; } }; classB2:public B1 { public: B2(){cout<<"B2 constructor"<<endl;}; virtualvoid v2(){ cout <<"B2::v2"<< endl; } }; classB3:public B1 { public: B3(){cout<<"B3 constructor"<<endl;}; virtualvoid v3(){ cout <<"B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :publicvirtualB2,publicvirtualB3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){cout <<"D::v3" <<endl; } virtual voidvD(){ cout << "D::vD"<< endl; } }; intmain (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
如果D中无虚函数,具体结果如下图
D中无虚函数,各个类的size如左下图
如果D中有虚函数,各个类的size如右上图,具体的类结构见下图:
B2和B3虚拟继承B1(此时B1有无虚函数有影响),D虚拟继承B2、B3,那么B2、B3、D有无虚函数对B2、B3、都有D有影响
#include <iostream> using namespace std; //查看虚函数表 classB{}; classB1 { public: B1(){cout<<"B1 constructor"<<endl;}; virtual voidv1(){ cout << "B1::v1"<< endl; } }; classB2:publicvirtualB1 { public: B2(){cout<<"B2 constructor"<<endl;}; virtualvoid v2(){ cout <<"B2::v2"<< endl; } void f2(){ cout << "B2::f2" << endl; } }; classB3:public virtual B1 { public: B3(){cout<<"B3 constructor"<<endl;}; virtualvoid v3(){ cout <<"B3::v3"<< endl; } void f3(){ cout << "B3::f3" << endl; } }; classD :publicvirtualB2,publicvirtualB3 { public: D(){cout<<"D constructor"<<endl;}; void v3(){cout <<"D::v3" <<endl; } virtual voidvD(){ cout << "D::vD"<< endl; } }; //======================================= intmain (int argc,constchar * argv[]) { cout<<sizeof(B)<<endl; cout<<sizeof(B1)<<endl; cout<<sizeof(B2)<<endl; cout<<sizeof(B3)<<endl; cout<<sizeof(D)<<endl; D* d=new D; B1* b1=new B1; B2* b2=new B2; B3* b3=new B3; d->v3(); return 0; }
若D中没有虚函数,那么D的size为24,即为B2和B3的size之和即不会共享相同的B1中的对象,其他类的size不变。
上面的两个结果为类D中有无成员方法V3()的结果,有V3时D的size为28,没有V3时D的size为24.而在B1、B2、B3中有无非虚成员方法对各个类无影响。
上面的两个结果为类D有虚函数,并且D中有无成员方法V3()的结果,有V3时D的size为28,没有V3时D的size为24.而在B1、B2、B3中有无非虚成员方法对各个类无影响。
相关文章推荐
- 一个C++继承、虚函数和多态性的实例代码
- 虚继承和虚函数对c++对象存储模型的影响(类/对象的大小)
- [置顶] 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响
- [置顶] 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- c++普通继承、虚继承、虚函数对sizeof的影响
- Data语意学之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- C++ 06 继承与组合 (has-a is-a) 以及类大小的计算 虚基类对内存模型的影响(不考虑虚函数)
- C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- C++ 虚函数 虚继承
- 第三周:C++组合、继承、虚函数与多态【Boolean】
- C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中
- c++的结构体 继承 虚函数
- C++虚函数多态性的实现与分析+虚继承的实现与分析
- C++虚函数和虚继承
- struct使用继承c++代码实例及运行结果
- 共有继承,保护继承,私有继承的区别c++代码实例
- c++虚函数实现机制以及类继承中的内存分布
- C++虚函数探索笔记(2)——虚函数与多继承