关于C++虚继承、虚函数继承的几个例子

今天看虚继承以及虚函数继承时写了几个实例来加深一下理解。相关技术原理参见:c++虚继承对象的内存布局

代码1:

没有虚继承的情况下

#include<iostream>
using namespace std;
class A//定义基类A
{public:A(int i){ cout<<"A cons"<<endl;} 
		void virtual print(){cout<<"aaa"<<endl;};		
};

class B : public  A 
{public:B(int n):A(n){ cout<<"B cons"<<endl;} 
		void virtual print(){cout<<"bbb"<<endl;};
};

class C : public  A 
{public:C(int n):A(n){cout<<"C cons"<<endl; } 
	//	void  print(){};
};

class D :public B,public C //类D的构造函数,在初始化表中对所有基类初始化
{public:D(int n):B(n),C(n){ cout<<"D cons"<<endl;}
	//	void virtual print(){cout<<"ddd"<<endl;}
};

void main()
{
	D d(1);
	d.B::print(); 
	d.C::print();
	d.print();  //maybe the 'print' in base 'B' of class 'D' or the 'print' in base 'A' of base 'C' of class 'D'
	d.A::print(); //maybe the 'A' in base 'B' of class 'D' or the 'A' in base 'C' of class 'D'

	cout<<"size of A:"<<sizeof(A)<<endl;
	cout<<"size of B:"<<sizeof(B)<<endl;
	cout<<"size of C:"<<sizeof(C)<<endl;
	cout<<"size of D:"<<sizeof(D)<<endl;

}

运行结果:


代码2
有虚继承的情况下
#include<iostream>
using namespace std;
class A//定义基类A

{public:A(int i){ cout<<"A cons"<<endl;} 
		void virtual print(){cout<<"aaa"<<endl;}		
};

class B : public virtual A //A作为B的虚基类

{public:B(int n):A(n){ cout<<"B cons"<<endl;} 
		void virtual print(){cout<<"bbb"<<endl;};
};

class C : public virtual A //A作为C的虚基类

{public:C(int n):A(n){cout<<"C cons"<<endl; } 
	//	void virtual  print(){};
};

class D :public B,public C //类D的构造函数,在初始化表中对所有基类初始化

{public:D(int n):A(n),B(n),C(n){ cout<<"D cons"<<endl;}
	void virtual print(){cout<<"ddd"<<endl;};
};

void main()
{
	D d(1);

	d.B::print();
	d.C::print();
	d.print();   
	d.A::print(); 

	cout<<"size of A:"<<sizeof(A)<<endl;
	cout<<"size of B:"<<sizeof(B)<<endl;
	cout<<"size of C:"<<sizeof(C)<<endl;
	cout<<"size of D:"<<sizeof(D)<<endl;
}

运行结果:


代码3~5主要考察了虚继承的情况下各个类的size问题。。。相关技术原理参见 c++虚继承对象的内存布局
代码3:
#include <iostream>
using namespace std;

class A
{
//char k[3];
virtual aa(){};
};

class B : public  A
{
//char j[3]; //加入一个变量是为了看清楚class中的vfptr放在什么位置
public:
virtual bb(){};
virtual xx(){};
virtual aa(){};
};
class C : public  B
{
//char i[3];
public:
virtual cc(){};
};

int main()
{
	cout<<sizeof(A)<<endl;
	cout<<sizeof(B)<<endl;
	cout<<sizeof(C)<<endl;
	return 0;
}
运行结果:
4
4
4
因为B 和C没有添加任何数据成员,仅仅override类A的虚函数,所以大小不变。
基类含有虚函数,单从非virtual继承,并且派生类没有添加新的数据成员,就算继承一万次也是4,vptr还不是那一个吗?类的size会变吗?

代码4:
#include <iostream>
using namespace std;

class A
{
//char k[3];
virtual aa(){};
};

class B : public virtual  A
{
//char j[3]; //加入一个变量是为了看清楚class中的vfptr放在什么位置
public:
//virtual bb(){};
//virtual xx(){};
//virtual aa(){};
};
class C : public virtual B
{
//char i[3];
public:
//virtual cc(){};
};

int main()
{
	cout<<sizeof(A)<<endl;
	cout<<sizeof(B)<<endl;
	cout<<sizeof(C)<<endl;
	return 0;
}

运行结果:
4
8
12
代码5:
#include <iostream>
using namespace std;

class A
{
//char k[3];
virtual aa(){};
};

class B : public virtual  A
{
char j[3]; //加入一个变量是为了看清楚class中的vfptr放在什么位置
public:
virtual bb(){};
virtual xx(){};
virtual aa(){};
};
class C : public virtual B
{
char i[3];
public:
virtual cc(){};
};

int main()
{
	cout<<sizeof(A)<<endl;
	cout<<sizeof(B)<<endl;
	cout<<sizeof(C)<<endl;
	return 0;
}

运行结果:
4
16
28
分析:
1、对于class A,由于只有一个虚函数,那么必须得有一个对应的虚函数表,来记录对应的函数入口地址。同时在class A的内存空间中之需要有个vfptr_A指向该表。sizeof(A)也很容易确定,为4。
2、对于class B,由于class B虚基础了class A,同时还拥有自己的虚函数。那么class B中首先拥有一个vfptr_B,指向自己的虚函数表。还有char j[3],做一次alignment,一般大小为4。可虚继承该如何实现咧?this is 啊 problem!偶之前是不晓得的,还好C++ Object Model上有介绍。首先要通过加入一个虚l类指针(记vbptr_B_A)来指向其父类,然后还要包含父类的所有内容。有些复杂了,不过还不难想象。sizeof(B)= 4+4+4+4=16(vfptr_B、char j[3]做alignment、vbptr_B_A和class A)。
3、在接着是class C了。class C首先也得有个vfptr_C,然后是char i[3],然后是vbptr_C_B,然后是class B,所以sizeof(C)=4+4+4+16=28(vfptr_C、char i[3]做alignment、vbptr_C_A和class B)。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值