探索 VS下虛繼承實現的方法 1

2021-07-12 04:01:23 字數 1566 閱讀 3813

c++的虛繼承主要解決了資料冗餘與二義性的問題,起實現方法是什麼呢,我們先看一段**。

#includeusing namespace std;

class a

;class b1 : public a

;class b2 : public a

;class c : public b1, public b2

;int main()

這是乙個菱形繼承,直接訪問兩個域中的_num並賦不同值時,兩個域中的_num不會是同乙個數值,證明了c中含有兩個_num成員變數。當我們訪問c域的_num,系統無法識別到底是訪問b1所繼承下來的還是b2所被繼承下來的,這裡編譯器會報錯,這裡c的大小為8個位元組,調試點開監視視窗我們可以看到:

乙個c在不同域裡繼承了兩份a類的成員變數,這樣就造成了資料冗餘及二義性。

如何解決這個問題呢,c++中引入了關鍵字「vritual」在一代繼承時加入關鍵字,修改後我們的**為:

#includeusing namespace std;

class a

;class b1 : virtual public a

;class b2 : virtual public a

;class c : public b1, public b2

;int main()

這時我們發現通過c我們不但可以訪問到自己域的成員變數,還可以訪問到所繼承類的成員變數,並且,當給不同域的同名成員變數賦值之後,它們的外在表現都是同乙個值,這樣節解決了二義性與資料冗雜,為什麼說是外在表現呢,當我們開啟除錯視窗與記憶體時我們會看到:

除錯視窗:

除錯視窗中,c不但包含兩個父類的成員變數,還包含兩個父類共同的父類的成員變數,這時c的大小為12。更驚奇的是,無論我們通過那個網域名稱對其成員變數進行賦值,其他域的成員變數的值也會隨之改變,這時為什麼呢。這裡我們開啟記憶體監視視窗:

第乙個指標:

第二個指標:

我們可以發現,這兩個指標都為空,但是,在這兩個指標底下,卻有兩個數字,這兩個數字又恰好與存放這兩個位址內容所在位址到存放c成員變數所在位址的偏移相同。由此可以看出vs下實現virtual關鍵字解決菱形繼承的二義性與資料冗餘的方法是,通過指標的偏移,使c中所存在的三塊空間,在直接或間接的條件下,指向同一塊空間。

未完待續

本文出自 「pawnsir的it之路」 部落格,請務必保留此出處

虛方法的呼叫是怎麼實現的 單繼承VS多繼承

我們知道通過乙個指向之類的父類指標可以呼叫子類的虛方法,因為子類的方法會覆蓋父類同樣的方法,通過這個指標可以找到物件例項的位址,通過例項的位址可以找到指向對應方法表的指標,而通過這個方法的名字就可以確定這個方法在方法表中的位置,直接呼叫就行,在多繼承的時候,乙個類可能有多個方法表,也就有多個指向這些...

虛方法的呼叫是怎麼實現的 單繼承VS多繼承

我們知道通過乙個指向之類的父類指標可以呼叫子類的虛方法,因為子類的方法會覆蓋父類同樣的方法,通過這個指標可以找到物件例項的位址,通過例項的位址可以找到指向對應方法表的指標,而通過這個方法的名字就可以確定這個方法在方法表中的位置,直接呼叫就行,在多繼承的時候,乙個類可能有多個方法表,也就有多個指向這些...

探索多型的實現 虛表

上次說到了多型,可是多型在編譯器裡到底是如何實現的呢?下面我們就來探索一下它深層的實現機制 我們可以從監視視窗來看一下 這張表解決了繼承 虛函式 重寫 的問題 有虛函式就有虛表 從父類繼承就自動生成了 虛函式表就像乙個路標,指明了實際應該呼叫哪個虛函式 還是用我最喜歡的圖示來說明,下圖 我們還是來看...