關於C++中的虛擬繼承的一些總結

來源:互聯網
上載者:User

1.為什麼要引入虛擬繼承

虛擬繼承是多重繼承中特有的概念。虛擬基類是為解決多重繼承而出現的。如:類D繼承自類B1、B2,而類B1、B2都繼承自類A,因此在類D中兩次出現類A中的變數和函數。為了節省記憶體空間,可以將B1、B2對A的繼承定義為虛擬繼承,而A就成了虛擬基類。實現的代碼如下:

class A

class B1:public virtual A;

class B2:public virtual A;

class D:public B1,public B2;

虛擬繼承在一般的應用中很少用到,所以也往往被忽視,這也主要是因為在C++中,多重繼承是不推薦的,也並不常用,而一旦離開了多重繼承,虛擬繼承就完全失去了存在的必要因為這樣只會降低效率和佔用更多的空間。

 

2.引入虛繼承和直接繼承會有什麼區別呢

由於有了間接性和共用性兩個特徵,所以決定了虛繼承體系下的對象在訪問時必然會在時間和空間上與一般情況有較大不同。

2.1時間:在通過繼承類對象訪問虛基類對象中的成員(包括資料成員和函數成員)時,都必須通過某種間接引用來完成,這樣會增加引用定址時間(就和虛函數一樣),其實就是調整this指標以指向虛基類對象,只不過這個調整是已耗用時間接完成的。

2.2空間:由於共用所以不必要在對象記憶體中儲存多份虛基類子物件的拷貝,這樣較之多繼承節省空間的。虛擬繼承與普通繼承不同的是,虛擬繼承可以防止出現diamond繼承時,一個衍生類別中同時出現了兩個基類的子物件。也就是說,為了保證這一點,在虛擬繼承情況下,基類子物件的布局是不同於普通繼承的。因此,它需要多出一個指向基類子物件的指標。

 

3.筆試,面試中常考的C++虛擬繼承的知識點

第一種情況:         第二種情況:          第三種情況            第四種情況:
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();
                               };                };

如果對這四種情況分別求sizeof(a),  sizeof(b)。結果是什麼樣的呢?下面是輸出結果:(在vc6.0中運行)
第一種:4,12
第二種:4,4
第三種:8,16
第四種:8,8

想想這是為什麼呢?

因為每個存在虛函數的類都要有一個4位元組的指標指向自己的虛函數表,所以每種情況的類a所佔的位元組數應該是沒有什麼問題的,那麼類b的位元組數怎麼算呢?看“第一種”和“第三種”情況採用的是虛繼承,那麼這時候就要有這樣的一個指標vptr_b_a,這個指標叫虛類指標,也是四個位元組;還要包括類a的位元組數,所以類b的位元組數就求出來了。而“第二種”和“第四種”情況則不包括vptr_b_a這個指標,這回應該木有問題了吧。

 

4.c++重載、覆蓋、隱藏的區別和執行方式

既然說到了繼承的問題,那麼不妨討論一下經常提到的重載,覆蓋和隱藏
4.1成員函數被重載的特徵
(1)相同的範圍(在同一個類中);
(2)函數名字相同;
(3)參數不同;
(4)virtual 關鍵字可有可無。
4.2“覆蓋”是指衍生類別函數覆蓋基類函數,特徵是:
(1)不同的範圍(分別位於衍生類別與基類);
(2)函數名字相同;
(3)參數相同;
(4)基類函數必須有virtual 關鍵字。
4.3“隱藏”是指衍生類別的函數屏蔽了與其同名的基類函數,特徵是:

(1)如果衍生類別的函數與基類的函數同名,但是參數不同,此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)如果衍生類別的函數與基類的函數同名,但是參數相同,但是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)。

小結:說白了就是如果衍生類別和基類的函數名和參數都相同,屬於覆蓋,這是可以理解的吧,完全一樣當然要覆蓋了;如果只是函數名相同,參數並不相同,則屬於隱藏。

4.4 三種情況怎麼執行:

4.4.1 重載:看參數。

4.4.2 隱藏:用什麼就調用什麼。

4.4.3 覆蓋:調用衍生類別。

            學習中的一點總結,歡迎拍磚哦^^

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.