C++虚继承对象模型
2010-10-21 12:36
253 查看
1.为什么需要虚继承
如下图所示如果访问Der::Fun or Der::m_nValue就会带来二义性,无法确定是调用Base1的还是Base2的,所以为了解决多重继承情况下成员访问的二义性,引入了虚继承机制。
一般继承 虚继承
2.虚继承实现
在虚继承下,Der通过共享虚基类SuperBase来避免二义性,在Base1,Base2中分别保存虚基类指针,Der继承Base1,Base2,包含Base1, Base2的虚基类指针,并指向同一块内存区,这样Der便可以间接存取虚基类的成员,如下图所示:
3.不同编译器实现方式
不同编译器对间接存取的方法不同,以下以GCC和VC为例,均采用以下代码进行实验:
class SuperBase
{
public:
int m_nValue;
void Fun(){cout<<"SuperBase1"<<endl;}
virtual ~SuperBase(){}
};
class Base1: virtual public SuperBase
{
public:
virtual ~ Base1(){}
};
class Base2: virtual public SuperBase
{
public:
virtual ~ Base2(){}
};
class Der:public Base1, public Base2
{
public:
virtual ~ Der(){}
};
void main()
{
cout<<sizeof(SuperBase)<<sizeof(Base1)<<sizeof(Base2)<<sizeof(Der)<<endl;
}
1) GCC中结果为8, 12, 12, 16
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + 虚函数指针 + 虚基类指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2虚基类指针 + 虚函数指针
GCC共享虚函数表指针,也就是说父类如果已经有虚函数表指针,那么子类中共享父类的虚函数表指针空间,不在占用额外的空间,这一点与VC不同,VC在虚继承情况下,不共享父类虚函数表指针,详见如下。
2)VC中结果为:8, 16, 16, 24
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + SuperBase虚函数指针 + 虚基类指针 + 自身虚函数指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2中虚基类指针 + Base1虚函数指针 + Base2虚函数指针 + 自身虚函数指针
如果去掉虚继承,结果将和GCC结果一样,A,B,C都是8,D为16,原因就是VC的编译器对于非虚继承,父类和子类是共享虚函数表指针的。
如下图所示如果访问Der::Fun or Der::m_nValue就会带来二义性,无法确定是调用Base1的还是Base2的,所以为了解决多重继承情况下成员访问的二义性,引入了虚继承机制。
一般继承 虚继承
2.虚继承实现
在虚继承下,Der通过共享虚基类SuperBase来避免二义性,在Base1,Base2中分别保存虚基类指针,Der继承Base1,Base2,包含Base1, Base2的虚基类指针,并指向同一块内存区,这样Der便可以间接存取虚基类的成员,如下图所示:
3.不同编译器实现方式
不同编译器对间接存取的方法不同,以下以GCC和VC为例,均采用以下代码进行实验:
class SuperBase
{
public:
int m_nValue;
void Fun(){cout<<"SuperBase1"<<endl;}
virtual ~SuperBase(){}
};
class Base1: virtual public SuperBase
{
public:
virtual ~ Base1(){}
};
class Base2: virtual public SuperBase
{
public:
virtual ~ Base2(){}
};
class Der:public Base1, public Base2
{
public:
virtual ~ Der(){}
};
void main()
{
cout<<sizeof(SuperBase)<<sizeof(Base1)<<sizeof(Base2)<<sizeof(Der)<<endl;
}
1) GCC中结果为8, 12, 12, 16
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + 虚函数指针 + 虚基类指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2虚基类指针 + 虚函数指针
GCC共享虚函数表指针,也就是说父类如果已经有虚函数表指针,那么子类中共享父类的虚函数表指针空间,不在占用额外的空间,这一点与VC不同,VC在虚继承情况下,不共享父类虚函数表指针,详见如下。
2)VC中结果为:8, 16, 16, 24
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + SuperBase虚函数指针 + 虚基类指针 + 自身虚函数指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2中虚基类指针 + Base1虚函数指针 + Base2虚函数指针 + 自身虚函数指针
如果去掉虚继承,结果将和GCC结果一样,A,B,C都是8,D为16,原因就是VC的编译器对于非虚继承,父类和子类是共享虚函数表指针的。
相关文章推荐
- C++对象模型----重复继承
- C++继承内存对象模型
- C++虚拟多重继承对象模型讨论
- C++对象模型 多重继承与虚函数表
- 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响
- C++ 继承中的对象模型
- C++多重继承和虚拟继承对象模型、效率分析
- C++虚继承内存对象模型探讨
- C++虚继承内存对象模型探讨
- 深度探索C++对象模型--继承与Data Member
- C++对象模型-----多继承
- [置顶] 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- C++对象模型3--无重写的单继承
- 浅谈c++继承与对象模型
- 深入探索C++对象模型之虚继承
- c++对象模型之菱形继承
- C++ 虚继承和虚函数同时存在的对象模型
- C++对象模型中数据成员与继承
- [置顶] 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类/对象的大小)
- 探索C++对象模型之 多重继承与虚函数表