這篇文章將為大家詳細(xì)講解有關(guān)C++中菱形繼承和虛繼承的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名與空間、網(wǎng)頁(yè)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、瑪多網(wǎng)站維護(hù)、網(wǎng)站推廣。繼承:
1. 單繼承–一個(gè)子類(lèi)只有一個(gè)直接父類(lèi)時(shí)稱(chēng)這個(gè)繼承關(guān)系為單繼承
2. 多繼承–一個(gè)子類(lèi)有兩個(gè)或以上直接父類(lèi)時(shí)稱(chēng)這個(gè)繼承關(guān)系為多繼承
例如下面這兩個(gè)例子:
例一(單繼承):
class A { public: int _a; }; class B : public A // B是 子類(lèi)/派生類(lèi), 公有 繼承父類(lèi)/基類(lèi) A { public: int _b; }; class C : public B //C是 子類(lèi)/派生類(lèi), 公有繼承 父類(lèi)/基類(lèi) B { public: int _c; };
例二(多繼承):
class A { public: int _a; }; class B { public: int _b; }; class C : public A , public B // 子類(lèi)C同時(shí)公有繼承父類(lèi)A和父類(lèi)B { public: int _c; };
用圖很形象的表示一下:
但是在使用過(guò)程中,很容易出現(xiàn)一種繼承關(guān)系叫菱形繼承。就好比下面這種繼承方式。
class A { public: int _a; }; class B : public A { public: int _b; }; class C : public A { public: int _c; }; class D : public B, public C { public: int _d; };
繼承的方式簡(jiǎn)單畫(huà)出來(lái)就是下面這樣:
我們?cè)谑褂眠^(guò)程中會(huì)發(fā)現(xiàn)以下缺點(diǎn):
1、 當(dāng)我們用D類(lèi)創(chuàng)建出對(duì)象d時(shí),可以訪問(wèn)到_a,但是一旦編譯就會(huì)出現(xiàn)錯(cuò)誤。錯(cuò)誤說(shuō)明為: C2385: 對(duì)“_a”的訪問(wèn)不明確。從圖中也可以看出,如果用d訪問(wèn)_a時(shí),可能在B類(lèi)里,也同時(shí)可能存在于c類(lèi)中。這就是所謂的“二義性”;
2、雖然B類(lèi)和C類(lèi)都公有繼承A,但是在D類(lèi)公有繼承B,C時(shí),存放了兩份A類(lèi),造成了數(shù)據(jù)的冗余。
C++針對(duì)這種缺陷提出了另外一種繼承方式叫做虛繼承。
虛繼承
C++使用虛擬繼承(Virtual Inheritance),解決從不同途徑繼承來(lái)的同名的數(shù)據(jù)成員在內(nèi)存中有不同的拷貝造成數(shù)據(jù)不一致問(wèn)題,將共同基類(lèi)設(shè)置為虛基類(lèi)。這時(shí)從不同的路徑繼承過(guò)來(lái)的同名數(shù)據(jù)成員在內(nèi)存中就只有一個(gè)拷貝,同一個(gè)函數(shù)名也只有一個(gè)映射。
◇語(yǔ)法:
class 派生類(lèi): virtual 基類(lèi)1,virtual 基類(lèi)2,…,virtual 基類(lèi)n { …//派生類(lèi)成員聲明 };
在有了虛繼承的概念后,我們就可以規(guī)避上面的缺點(diǎn)了。
class A { public: int _a; }; class B : virtual public A { public: int _b; }; class C : virtual public A { public: int _c; }; class D : public B, public C { public: int _d; };
當(dāng)我們使用了虛繼承時(shí),繼承模型就改變?yōu)橄旅孢@樣:
由于我所使用的是vs2015,在此編譯器下對(duì)應(yīng)的處理方式就是這樣。將class B 和 class C設(shè)置為虛繼承后,編譯器將class A存放在了最下端,并在B和C類(lèi)的前四個(gè)字節(jié)中存放了一個(gè)地址,當(dāng)我們?cè)L問(wèn)過(guò)去向下再多看四個(gè)字節(jié)時(shí)就會(huì)發(fā)現(xiàn)這其中存放了一個(gè)數(shù)字。而這個(gè)數(shù)字就類(lèi)似于“偏移量”,記錄了該類(lèi)的首地址距父類(lèi)首地址之間的字節(jié)差距。比如class B中,我們找到對(duì)應(yīng)數(shù)字為14,但是這個(gè)數(shù)字是16進(jìn)制,轉(zhuǎn)為10進(jìn)制為20,在class B的首地址加上20個(gè)字節(jié)就恰好是class A的首地址,同理class C。
因此在class D訪問(wèn)_a時(shí),就不會(huì)產(chǎn)生二義性,_a數(shù)據(jù)也只存放了一份,解決了之前菱形繼承所帶來(lái)的問(wèn)題。
但是還存在一個(gè)問(wèn)題:當(dāng)我們求沒(méi)有使用虛繼承之前的class D的大小,結(jié)果是20,但是在使用了虛繼承后大小變?yōu)?4。所以雖然使用虛繼承解決數(shù)據(jù)冗余問(wèn)題也帶來(lái)了性能上的損耗。(關(guān)于如何計(jì)算內(nèi)存大小,可以參考此鏈接。)
關(guān)于“C++中菱形繼承和虛繼承的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。