有時候,你真的需要看一些代碼/圖表:)請注意,標準中沒有提到這個實現細節。
首先,讓我們看看如何實現用C方法++:
struct Base
{
void foo();
};
這是類似的:
struct Base {};
void Base_foo(Base& b);
而事實上,當你看到一個方法調用一個調試器中,您經常會將this
參數看作第一個參數。它有時被稱爲隱式參數。
現在,上虛擬表。在C和C++中,可以使指針起作用。 V表基本上是函數指針表:
struct Base
{
int a;
};
void Base_set(Base& b, int i) { b.a = i; }
int Base_get(Base const& b) { return b.a; }
struct BaseVTable
{
typedef void (*setter_t)(Base&, int);
typedef int (*getter_t)(Base const&);
setter_t mSetter;
getter_t mGetter;
BaseVTable(setter_t s, getter_t g): mSetter(s), mGetter(g) {}
} gBaseVTable(&Base_set, &Base_get);
現在我可以這樣做:現在
void func()
{
Base b;
(*gBaseVTable.mSetter)(b, 3);
std::cout << (*gBaseVTable.mGetter)(b) << std::endl; // print 3
}
,就到了繼承。讓我們創建另一個結構
struct Derived: Base {}; // yeah, Base does not have a virtual destructor... shh
void Derived_set(Derived& d, int i) { d.a = i+1; }
struct DerivedBaseVTable
{
typedef void (*setter_t)(Derived&,int);
typedef BaseVTable::getter_t getter_t;
setter_t mSetter;
getter_t mGetter;
DerivedBaseVTable(setter_t s, getter_t g): mSetter(s), mGetter(g) {}
} gDerivedBaseVTable(&Derived_set, &Base_get);
而且使用:
void func()
{
Derived d;
(*gDerivedBaseVTable.mSetter)(d, 3);
std::cout << (*gDerivedBaseVTable.mGetter)(d) << std::endl; // print 4
}
但如何實現自動化嗎?
- 你只需要具有至少一個虛函數
- 類的每個實例都將包含一個指向虛函數表作爲它的第一個屬性(即使你真的不能訪問每類虛函數表的一個實例它自己)
現在,在多重繼承的情況下會發生什麼?那麼,繼承是非常像的存儲器佈局術語組合物:
| Derived |
| BaseA | BaseB |
| vpointer | field1 | field2 | padding? | vpointer | field1 | field2 | padding? |
有將因此成爲MostDerived
2個虛擬表:一個以改變從BaseA
和一個方法來從BaseB
改變方法。
純虛函數通常表示爲一個空指針(簡單地)在相應的字段中。
最後,建築和破壞:
施工
BaseA
構造:首先vpointer被初始化,則屬性,則該構造的主體被執行
BaseB
被構造:vpointer,attributes,body
Derived
構造:替換vpointers(兩者),屬性,主體
破壞
Derived is destructed
:析構函數的身體,破壞屬性,把基地vpointers回
BaseB
被破壞:身體屬性
BaseA
被破壞:身體屬性
我認爲它非常全面,如果一些C++大師在那裏可以檢查一下並檢查我哈哈,我會很高興沒有犯任何愚蠢的錯誤。另外,如果缺少某些東西,我很樂意添加它。
真的很全面的答案!非常感謝! – Bruce 2010-07-05 13:33:17
虛擬繼承期間會發生什麼?你如何解釋蝙蝠在虛擬繼承之後變成了(vpointer,Mammal,vpointer,WingedAnimal,Bat,Animal)? – Bruce 2010-07-05 15:02:38
這裏的「蝙蝠」是一個錯誤(會導致無限遞歸)而忽略它。在虛擬繼承的情況下,虛擬繼承的類只能被一個(通過派生類最多)實例化,但顯然在「Mammal」和「WingedAnimal」部分之前。 – 2010-07-05 16:16:48