以下均为博主在阅读侯捷老师翻译的《深度探索c++对象模型》时所做的笔记以及相关感悟:
方式一:
当有虚基类时,直接设置指向虚基类位置的指针(这种情况下可能会发生多级指针的问题)。
方式二:
采用两个表分别来记录虚基类以及虚函数,那么也就需要两个相应的指针来维护,且虚基类表中存放的是虚基类的位置。
方式三
和方式二相比,和虚函数共用一张表,但是在表中采用一定的标识来区分虚函数和虚基类,例如用正负索引。
具体例子
class A {
public:
int x;
int y;
public:
virtual void foo(){cout<<"huhu"<<endl;}
};
class B :virtual public A{
public:
int m;
public:
void foo(){cout<<"huhu"<<endl;}
void fee(){}
};
我们在64位GCC编译器中运行求解B的大小得到大小为32bytes,此时我们可以知道GCC编译器中虚基类和虚表分为了2个不同的表。
再运行以下代码:
#include<iostream>
using namespace std;
class A {
public:
int x;
int y;
public:
virtual void foo(){cout<<"huhu"<<endl;}
};
class B :public A{
public:
int m;
public:
void foo(){cout<<"huhu"<<endl;}
virtual void fee(){}
};
class C :public B{
public:
void fee(){cout<<"hixi"<<endl;}
};
class D {
public :
virtual void f(){cout<<"ndr"<<endl;}
};
class E: public C,public D
{
void f(){cout<<"pipi"<<endl;}
};
int main()
{
cout<<sizeof(int*)<<endl;
cout<<&(((A*)0)->x)<<endl;
cout<<sizeof(E)<<" "<<sizeof(C)<<endl;
return 0;
}
得到结果为:
此时我们可以猜测虚函数表在类的起始位置,虚基类表在类的末端位置。
拓展
类的单一继承结构(并含有虚函数)为:
类的多重继承结构为:
要注意:上述的一些结构重要的是设计思想,具体实现时可能因为不同编译器而有偏差!!!