關(guān)于C++中虛擬繼承的一些總結(jié)分析
1.為什么要引入虛擬繼承
虛擬繼承是多重繼承中特有的概念。虛擬基類是為解決多重繼承而出現(xiàn)的。如:類D繼承自類B1、B2,而類B1、B2都繼承自類A,因此在類D中兩次出現(xiàn)類A中的變量和函數(shù)。為了節(jié)省內(nèi)存空間,可以將B1、B2對(duì)A的繼承定義為虛擬繼承,而A就成了虛擬基類。實(shí)現(xiàn)的代碼如下:
class A
class B1:public virtual A;
class B2:public virtual A;
class D:public B1,public B2;
虛擬繼承在一般的應(yīng)用中很少用到,所以也往往被忽視,這也主要是因?yàn)樵贑++中,多重繼承是不推薦的,也并不常用,而一旦離開了多重繼承,虛擬繼承就完全失去了存在的必要因?yàn)檫@樣只會(huì)降低效率和占用更多的空間。
2.引入虛繼承和直接繼承會(huì)有什么區(qū)別呢
由于有了間接性和共享性兩個(gè)特征,所以決定了虛繼承體系下的對(duì)象在訪問時(shí)必然會(huì)在時(shí)間和空間上與一般情況有較大不同。
2.1時(shí)間:在通過繼承類對(duì)象訪問虛基類對(duì)象中的成員(包括數(shù)據(jù)成員和函數(shù)成員)時(shí),都必須通過某種間接引用來完成,這樣會(huì)增加引用尋址時(shí)間(就和虛函數(shù)一樣),其實(shí)就是調(diào)整this指針以指向虛基類對(duì)象,只不過這個(gè)調(diào)整是運(yùn)行時(shí)間接完成的。
2.2空間:由于共享所以不必要在對(duì)象內(nèi)存中保存多份虛基類子對(duì)象的拷貝,這樣較之多繼承節(jié)省空間。虛擬繼承與普通繼承不同的是,虛擬繼承可以防止出現(xiàn)diamond繼承時(shí),一個(gè)派生類中同時(shí)出現(xiàn)了兩個(gè)基類的子對(duì)象。也就是說,為了保證這一點(diǎn),在虛擬繼承情況下,基類子對(duì)象的布局是不同于普通繼承的。因此,它需要多出一個(gè)指向基類子對(duì)象的指針。
3.筆試,面試中??嫉腃++虛擬繼承的知識(shí)點(diǎn)
第一種情況: 第二種情況: 第三種情況 第四種情況:
class a class a class a class a
{ { { {
virtual void func(); virtual void func(); virtual void func(); virtual void func();
}; }; char x; char x;
class b:public virtual a class b :public a }; };
{ { class b:public virtual a class b:public a
virtual void foo(); virtual void foo(); { {
}; }; virtual void foo(); virtual void foo();
如果對(duì)這四種情況分別求sizeof(a), sizeof(b)。結(jié)果是什么樣的呢?下面是輸出結(jié)果:(在vc6.0中運(yùn)行)
第一種:4,12
第二種:4,4
第三種:8,16
第四種:8,8
想想這是為什么呢?
因?yàn)槊總€(gè)存在虛函數(shù)的類都要有一個(gè)4字節(jié)的指針指向自己的虛函數(shù)表,所以每種情況的類a所占的字節(jié)數(shù)應(yīng)該是沒有什么問題的,那么類b的字節(jié)數(shù)怎么算呢?看“第一種”和“第三種”情況采用的是虛繼承,那么這時(shí)候就要有這樣的一個(gè)指針vptr_b_a,這個(gè)指針叫虛類指針,也是四個(gè)字節(jié);還要包括類a的字節(jié)數(shù),所以類b的字節(jié)數(shù)就求出來了。而“第二種”和“第四種”情況則不包括vptr_b_a這個(gè)指針,這回應(yīng)該木有問題了吧。
4.c++重載、覆蓋、隱藏的區(qū)別和執(zhí)行方式
既然說到了繼承的問題,那么不妨討論一下經(jīng)常提到的重載,覆蓋和隱藏
4.1成員函數(shù)被重載的特征
(1)相同的范圍(在同一個(gè)類中);
(2)函數(shù)名字相同;
(3)參數(shù)不同;
(4)virtual 關(guān)鍵字可有可無。
4.2“覆蓋”是指派生類函數(shù)覆蓋基類函數(shù),特征是:
(1)不同的范圍(分別位于派生類與基類);
(2)函數(shù)名字相同;
(3)參數(shù)相同;
(4)基類函數(shù)必須有virtual 關(guān)鍵字。
4.3“隱藏”是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù),特征是:
(1)如果派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)不同,此時(shí),不論有無virtual關(guān)鍵字,基類的函數(shù)將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)相同,但是基類函數(shù)沒有virtual 關(guān)鍵字。此時(shí),基類的函數(shù)被隱藏(注意別與覆蓋混淆)。
小結(jié):說白了就是如果派生類和基類的函數(shù)名和參數(shù)都相同,屬于覆蓋,這是可以理解的吧,完全一樣當(dāng)然要覆蓋了;如果只是函數(shù)名相同,參數(shù)并不相同,則屬于隱藏。
4.4 三種情況怎么執(zhí)行:
4.4.1 重載:看參數(shù)。
4.4.2 隱藏:用什么就調(diào)用什么。
4.4.3 覆蓋:調(diào)用派生類。
相關(guān)文章
VS2019實(shí)現(xiàn)C++的第一個(gè)MFC程序
本文主要介紹了VS2019實(shí)現(xiàn)C++的第一個(gè)MFC程序,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06C++實(shí)現(xiàn)簡(jiǎn)易UDP網(wǎng)絡(luò)聊天室
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)易UDP網(wǎng)絡(luò)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07opencv3/C++實(shí)現(xiàn)霍夫圓/直線檢測(cè)
今天小編就為大家分享一篇opencv3/C++實(shí)現(xiàn)霍夫圓/直線檢測(cè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12C語言經(jīng)典算法例題求100-999之間的“水仙花數(shù)”
本文的主要內(nèi)容,設(shè)計(jì)一個(gè)程序,找出100-999之間的“水仙花數(shù)”,需要的朋友可以參考下2015-07-07C++關(guān)鍵字volatile學(xué)習(xí)筆記
這篇文章主要為大家介紹了C++關(guān)鍵字volatile學(xué)習(xí)筆記,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10