C++物件版面配置及多態探索之菱形結構虛繼承

來源:互聯網
上載者:User

這次我們看看菱形結構的虛繼承。虛繼承的引入本就是為瞭解決複雜結構的繼承體系問題。上一篇我們在討論虛繼承時用的是一個簡單的繼承結構,只是為了打個鋪墊。

我們先看看這幾個類,這是一個典型的菱形繼承結構。C100和C101通過虛繼承共用同一個父類C041。C110則從C100和C101多重繼承而來。

struct C041
{
 C041() : c_(0x01) {}
 virtual void foo() { c_ = 0x02; }
 char c_;
};
struct C100 : public virtual C041
{
 C100() : c_(0x02) {}
 char c_;
};
struct C101 : public virtual C041
{
 C101() : c_(0x03) {}
 char c_;
};
struct C110 : public C100, public C101
{
 C110() : c_(0x04) {}
 char c_;
};

運行如下代碼:

PRINT_SIZE_DETAIL(C110)

結果為:

The size of C110 is 16
The detail of C110 is 28 c3 45 00 02 1c c3 45 00 03 04 18 c3 45 00 01

我們可以象上一篇一樣,畫出對象的記憶體布局。

|C100,5 |C101,5 |C110,1 |C041,5 |
|ospt,4,11 |m,1 |ospt,4,6 |m,1 |m,1 |vtpt,4 |m1 |

(註:為了不折行,我用了縮寫。ospt代表位移值指標、m代表成員變數、vtpt代表虛表指標。第一個數字是該地區的大小,即位元組數。只有位移值指標有第二個數字,第二個數字就是位移值指標指向的位移值的大小。)

可以看到對象的記憶體布局中只有一個C041,即祖父類的部分只有一份,且放在最後面。這就是菱形繼承。對比前面幾篇的討論,我們可以知道,如果沒有用虛繼承機制,那麼在C041對象的記憶體布局中會出現兩份C041部分,這也就是所謂的V型繼承。相應的物件版面配置為:C041+C100+C041+C101 +C110。在V型繼承中是不能直接從C110,即孫子類,直接轉型到C041,即祖父類的。因為在對象的布局中有兩份祖父類的實體,一份從C100而來,一份從C101而來。編譯器在決議時會存在二義性,它不知道轉型後到底用哪一份實體。雖然可以通過先轉型到某一父類,然後再轉型到祖父類來解決。但使用這種方法時,如果改寫了祖父類的成員變數的內容,runtime是不會同步兩個祖父類實體的狀態,因此可能會有語義錯誤。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.