虛函式表和C 抽象基類

2021-06-02 02:14:16 字數 2284 閱讀 1078

為什麼用

c++的純抽象基類來實現

com介面是可行的呢?這主要是由於純抽象類說定義的記憶體結構可以滿足

com對介面的需求。

當定義乙個純抽象基類時,實際上定義的是乙個記憶體塊的結構,且其所有的實現都是一些具有相同的基本結構的記憶體塊。但是,此記憶體只有在派生類中實現此抽象基類時才會被分配。繼承抽象基類的派生類,也將繼承此記憶體結構。

inte***ce ix

;

由圖1可以看出,乙個純抽象基類所定義的記憶體結構包含兩部分:虛函式表vtable和指向vtable的指標vtable pointer。其中,指向抽象基類的指標指向此vtable指標,而vtable指標則指向虛函式表vtable。vtable中包含一組指向虛函式實現的指標,例如圖1的第一項為派生類中所實現的fx1函式的位址,第二項則是fx2的位址....

com介面的記憶體結構同c++編譯器為抽象基類所生成的記憶體結構是相同的。因此,可以合用抽象基類來定義com介面。所上面的com抽象基類ix是乙個com介面,是由於其記憶體結構符合com規範的要求。但是,對於乙個com介面還有其他的一些需求。例如,所有的com介面都必須繼承乙個名為iunkown的介面。這意味著,所有com介面的前三個項都是相同的,其中儲存的是iunkown中三個成員函式的實現的位址。

vtable

指標有什麼用途呢?

vtable

指標在由抽象基類函式指標到函式的過程中增加了乙個額外的級別,正是這一額外的級別給介面的實現帶來了極大的靈活性。

c++編譯器生成**時,實現抽象基類的類可能會將特定於例項的資訊同

vtable

一塊儲存。例如,

ca實現了抽象基類

ix,**如下:

class ca: public ix

virtual void __stdcall fx2()

virtual void __stdcall fx3()

virtual void __stdcall fx4()

//constructor

ca(int i):m_ix1(i), m_ix2(i*i), m_ix3(i*i*i)

{}//inte***ce data

int m_ix1;

int m_ix2;

int m_ix3;

};

對於上面我們說說的編譯器,vtable和ca的類資料將如圖2所示。需要注意的是,例項資料理應是可以通過指向類的指標pa來訪問的,但是由於客戶通常並不知道例項資料是如何儲存的,因此客戶也就無法訪問它們了。

雖然c++可以直接操作和使用例項資料,但com元件絕不會訪問任何例項資料。在com中,對乙個元件的訪問只能通過函式完成,而絕不能直接通過變數來訪問。此外,純抽象基類只有虛函式,沒有任何例項資料

三:多重例項

vtable

的作用決不僅僅是給例項資料的儲存提供乙個方便的位置,實際上,同乙個類的不同例項還可以共享同一

vtable

。如果我們們建立了

ca的兩個不同的例項,那麼將會有兩組不同的例項資料,但不同的例項可以共享同一

vtable

及相同的實現(圖

3)。如:

int main()

可是,雖然com元件可以使用vtable指標來共享vtable,但這一點並不是必須的。com元件的每乙個例項都有乙個不同的vtable。

四:不同的類,相同的vtable

介面的真正威力在於繼承此介面的所有類均可以被客戶按同一方式進行處理。例如,類

cb也繼承了ix:

class cb: public ix

virtual void __stdcall fx2()

virtual void __stdcall fx3()

virtual void __stdcall fx4()

};這樣一來,客戶就可以通過同乙個ix指標來訪問ca和cb。

void f(ix* pix)

int main()

在這裡,我們將ca和cb都當作ix介面來使用,這是多型的乙個例子。此例子的記憶體結構如圖4所示。兩個類ca和cb分別具有不用的例項資料、vtable以及實現。但因它們的vtable具有相同的格式而可以按相同的方式來訪問。

圖4的這種格式是編譯器根據抽象基類的定義而生成的。在某個類實現抽象基類時,此時他將被強制使用此種格式。對於元件也將是這樣的。當元件返回乙個ix介面指標時,它必須保證此指標指向正確的結構。

C 抽象基類和純虛函式

為什麼c 要定義抽象基類?c 為什麼要定義抽象基類?抽象類就是類裡定義了純虛成員函式的類。純虛函式只提供了介面,並沒有具體實現。抽象類不能被例項化,通常是作為基類供子類繼承,子類中重寫虛函式,實現具體的介面。為什麼要定義抽象基類呢?依我所見主要有以下原因 1.最重要的原因是,可以將介面與實現分離。介...

c 純虛函式和抽象基類

c 物件導向程式設計的思想之一是可以使用繼承。繼承中乙個重要的思想是使用抽象基類 abstract base class,abc 假設我們開發乙個程式,需要使用橢圓和圓兩種圖形。因為圓是橢圓的一種特殊情形,根據繼承 is a 的思想,自然會想到先定義乙個eclipse類,再將circle類繼承自ec...

純虛函式和抽象基類

純虛函式的格式 virtual 型別 函式名 參數列 0 而我們的純虛函式經常被用來構建抽象基類。抽象基類 當我們僅想對基類進行向上型別轉換,使用它的介面,而不希望使用者實際地建立乙個基類的物件,那麼我們就在基類中加入至少乙個純虛函式 pure virtual function 來使基類稱為抽象 a...