簡單類
class Base
{
int a;
int b;
public:
void CommonFunction();
};
簡單類繼承
class DerivedClass: public Base
{
int c;
public:
void DerivedCommonFunction();
};
帶有虛函數的類
class Base
{
int a;
int b;
public:
void CommonFunction();
void virtual VirtualFunction();
};
虛函數類繼承
沒有復寫的繼承
class DerivedClass: public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
復寫的繼承
class DerivedClass1 : public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
void virtual VirtualFunction2();
};
多重繼承
class Base
{
int a;
int b;
public:
void CommonFunction();
void virtual VirtualFunction();
};
class DerivedClass1: public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedClass2 : public Base
{
int d;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedDerivedClass : public DerivedClass1, public DerivedClass2
{
int e;
public:
void DerivedDerivedCommonFunction();
void virtual VirtualFunction();
};
內存分布從父類到子類,依次如下:
Base中有一個虛表指針
DerivedClass1繼承了Base,內存排布是先父類后子類。
DerivedClass2的情況是類似於DerivedClass1的。
DerivedDerivedClass,由外向內看,它並列地排布着繼承而來的兩個父類DerivedClass1與DerivedClass2,還有自身的成員變量e。DerivedClass1包含了它的成員變量c,以及Base,Base有一個0地址偏移的虛表指針,然后是成員變量a和b;DerivedClass2的內存排布類似於DerivedClass1,注意到DerivedClass2里面竟然也有一份Base。
這里有兩份虛表了,分別針對DerivedClass1與DerivedClass2,在&DerivedDericedClass_meta下方的數字是首地址偏移量,靠下面的虛表的那個-16表示指向這個虛表的虛指針的內存偏移,這正是DerivedClass2中的{vfptr}在DerivedDerivedClass的內存偏移。
虛繼承
class DerivedClass1: virtual public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedClass2 : virtual public Base
{
int d;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedDerivedClass : public DerivedClass1, public DerivedClass2
{
int e;
public:
void DerivedDerivedCommonFunction();
void virtual VirtualFunction();
};
Base類沒有變化
DerivedClass1就已經有變化了,原來是先排虛表指針與Base成員變量,vfptr位於0地址偏移處;但現在有兩個虛表指針了,一個是vbptr,另一個是vfptr。vbptr是這個DerivedClass1對應的虛表指針,它指向DerivedClass1的虛表vbtable,另一個vfptr是虛基類表對應的虛指針,它指向vftable。
下面列出了兩張虛表,第一張表是vbptr指向的表,8表示{vbptr}與{vfptr}的偏移;第二張表是vfptr指向的表,-8指明了這張表所對應的虛指針位於內存的偏移量。
DerivedClass2的內存分布類似於DerivedClass1,同樣會有兩個虛指針,分別指向兩張虛表(第二張是虛基類表)。
下面來仔細看一下DerivedDerivedClass的內存分布,這里面有三個虛指針了,但base卻只有一份。第一張虛表是內含DerivedClass1的,20表示它的虛指針{vbptr}離虛基表指針{vfptr}的距離,第二張虛表是內含DerivedClass2的,12表示它的虛指針{vbptr}離虛基表指針{vfptr}的距離,最后一張表是虛基表,-20指明了它對應的虛指針{vfptr}在內存中的偏移。
虛繼承的作用是減少了對基類的重復,代價是增加了虛表指針的負擔(更多的虛表指針)。