您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)怎么在c++中利用虛函數(shù)實現(xiàn)多態(tài),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
#include<iostream> using namespace std; class CFather { public: virtual void AA() //虛函數(shù)標(biāo)識符 { cout << "CFather :: AA()" << endl; } void BB() { cout << "CFather :: BB()" << endl; } }; class CSon : public CFather { public: void AA() { cout << "CSon :: AA()" << endl; } void BB() { cout << "CSon :: BB()" << endl; } }; int main() { cout << sizeof(CFather) << endl; //測試加了虛函數(shù)的類 system("pause"); return 0; }
很明顯類里裝了一個 4個字節(jié)的東西,除了整形int,就是指針了,沒錯這里裝的就是函數(shù)指針
先把這個代碼,給抽象成圖形進行理解,在這CFather為A,CSon為B
此時就是一個單純的繼承的情況,不存在虛函數(shù),然后我new一個對象,A *p = new A;那么 p -> AA(),必然是指向A類中的AA()函數(shù),那么函數(shù)的調(diào)用有兩種方式 一種函數(shù)名加()直接調(diào)用,一種是利用函數(shù)指針進行調(diào)用,在這里我想要調(diào)用子類的,就可以利用函數(shù)指針進行調(diào)用,假設(shè)出來兩個函數(shù)指針,來指向B類中的兩個成員函數(shù),如果我父類想要調(diào)用子類成員,就可以通過 p指針去調(diào)用函數(shù)指針,再通過函數(shù)指針去調(diào)用成員函數(shù)
,
每一個函數(shù)都可以用一個函數(shù)指針去指著,那么每一類中的函數(shù)指針都可以形成自己的一個表,這個就叫做虛函數(shù)表
那么在創(chuàng)建對象后,為什么類中會有四個字節(jié)的內(nèi)存空間呢?
在C++的標(biāo)準(zhǔn)規(guī)格說明書中說到,編譯器必需要保證虛函數(shù)表的指針存在于對象中最前面的位置(這是為了保證正確取到虛函數(shù)的偏移量)。這意味著我們通過對象實例的地址得到這張?zhí)摵瘮?shù)表,然后就可以遍歷其中函數(shù)指針,并調(diào)用相應(yīng)的函數(shù)。也就是說這四個字節(jié)的指針,代替了上圖中(p->*pfn)()的作用,指向了函數(shù)指針,也就是說,在使用了虛函數(shù)的父類成員函數(shù),雖然寫的還是p->AA(),實際上卻是,(p->*(vfptr[0])),而指向哪個虛函數(shù)表就由,創(chuàng)建的對象來決定
至此,就能理解如何用虛函數(shù)這個機制來實現(xiàn)多態(tài)的了
下面,我將分別說明“無覆蓋”和“有覆蓋”時的虛函數(shù)表的樣子。沒有覆蓋父類的虛函數(shù)是毫無意義的。我之所以要講述沒有覆蓋的情況,主要目的是為了給一個對比。在比較之下,我們可以更加清楚地知道其內(nèi)部的具體實現(xiàn)。
無虛數(shù)覆蓋
下面,再讓我們來看看繼承時的虛函數(shù)表是什么樣的。假設(shè)有如下所示的一個繼承關(guān)系:
請注意,在這個繼承關(guān)系中,子類沒有重載任何父類的函數(shù)。那么,在派生類的實例中,Derive d; 的虛函表:
我們可以看到下面幾點:
1)虛函數(shù)按照其聲明順序放于表中。
2)父類的虛函數(shù)在子類的虛函數(shù)前面。
有虛數(shù)覆蓋
覆蓋父類的虛函數(shù)是很顯然的事情,不然,虛函數(shù)就變得毫無意義。下面,我們來看一下,如果子類中有虛函數(shù)重載了父類的虛函數(shù),會是一個什么樣子?假設(shè),我們有下面這樣的一個繼承關(guān)系。
為了讓大家看到被繼承過后的效果,在這個類的設(shè)計中,我只覆蓋了父類的一個函數(shù):f()。那么,對于派生類的實例,其虛函數(shù)表會是下面的一個樣子:
我們從表中可以看到下面幾點,
1)覆蓋的f()函數(shù)被放到了虛表中原來父類虛函數(shù)的位置。
2)沒有被覆蓋的函數(shù)依舊。
這樣,我們就可以看到對于下面這樣的程序,
Base *b = new Derive(); b->f();
看完上述內(nèi)容,你們對怎么在c++中利用虛函數(shù)實現(xiàn)多態(tài)有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。