1. 程式人生 > >關於c++中的virtual繼承的總結

關於c++中的virtual繼承的總結

1.在什麼時候需要虛擬繼承呢?

虛擬繼承是多重繼承特有的概念。虛擬基類是為了解決多重繼承而出現的。例如A繼承了Y,Z。而Y,Z繼承自X,因此A兩次出現了類x中的變數和函式,可以將Y,Z定義為虛擬繼承。而x則變成了虛擬繼承的基類

class X{ };

class Y: public virtual X{ };

class Z: public virtual X{ };

class A :public Y, public Z{ };

上述的X,Y,Z,A中都沒有任何一個class中含有明顯的資料,只表明了之間的繼承關係。所以認為每個的大小都為0?當然不對。即使是class X的大小也不為0;

#include<iostream>
using namespace std;
class A{


};


class B:public virtual A{


};


class C: public virtual A{


};


class D:public B,public C{


};


int main()
{
int a , b , c , d;


a = sizeof(A);
b = sizeof(B);
c = sizeof(C);
d = sizeof(D);


cout<<a << b <<c <<d<<endl;


return 0;
}

本程式在vc6.0執行的結果為:

1448
Press any key to continue

但是為了一個空的類會佔用這麼多的空間呢?

對於class A來說, 編譯器為空類X分配了一個char的空間,所以會佔用一個空間的位元組。

而對於b,c來說,都儲存了一個指向虛擬基類的指標。故佔用4個位元組,class D同理。

事實上b,c的大小受到了三個因素的影響

1.語言本身所造成的額外負擔。

當語言支援virtual base的時,就會導致一些額外的負擔,在diriver class中,這個額外的負擔就反應在某種形式的指標上面,他指向virtual base class subobject,或者是指向一個相關的表格(virtual table),表格中存放的不是virtual base class subobject的地址 ,就是他的偏移量。

2.編譯器對於特殊情況所提供的優化處理

3.alignment的限制

alignment就是數值調整到某數的整數倍,在32位計算機上面,通常alignment為4 byte ,以使bus的“運輸量”達到最高效率。

那麼虛擬繼承與直接繼承有什麼區別呢?

由於有了間接性和共享性兩個特徵,所以決定了虛繼承體系下的物件在訪問的時候必然會在時間和空間下有很大的不同。

1)。時間:在通過繼承訪問虛基類中的成員的時候,都必須通過某種間接來完成,這樣會增加引用定址空間。其實就是調整this指標指向虛基類物件,只不過這個調整是在執行期完成的。

2)空間:由於共享所以不必要在物件記憶體中儲存多份虛基類子物件的拷貝。這樣與多繼承相比,節約了空間。繼續繼承與普通繼承不同的是,虛擬繼承可以防止diamond繼承時,一個派生類出現了兩個基類的子物件。也就是說,為了保證這一點,在虛擬繼承的情況下,基類子物件的佈局是不同於普通繼承的。因此,他只需要多出一個指向基類子物件的指標。