现在的位置: 首页 > 综合 > 正文

用代码的角度看C++虚函数、虚继承的影响

2014年08月25日 ⁄ 综合 ⁄ 共 9987字 ⁄ 字号 评论关闭

一直以来,c++的虚函数以及虚继承令人讨厌。下面通过程序彻底了解c++的虚函数以及虚继承。

#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中没有虚函数,那么Dsize24,即为B2B3size之和即不会共享相同的B1中的对象,其他类的size不变。

上面的两个结果为类D中有无成员方法V3()的结果,有V3Dsize28,没有V3Dsize24.而在B1B2B3中有无非虚成员方法对各个类无影响。

上面的两个结果为类D有虚函数,并且D中有无成员方法V3()的结果,有V3Dsize28,没有V3Dsize24.而在B1B2B3中有无非虚成员方法对各个类无影响。

 

抱歉!评论已关闭.