C++繼承小知識點

5.C++子類繼承父類後子類的大小

#include <iostream>
using namespace std;
class  A 
{
private:
 int a;
};

class B:public  A
{
private:
 int b;
};

int main()
{
 cout<<sizeof(A)<<endl;
 cout<<sizeof(B)<<endl;
 return 0;
}

剛開始我一想子類繼承父類不會繼承父類的私有變量,如此我認爲結果爲4,4(錯誤)。而事實上結果是4,8。也就是說子類把父類的私有變量也繼承下來了,但是卻無法訪問,對於我這種菜鳥來說一下子沒法轉個彎來,後來看看資料煥然大悟,子類雖然無法直接訪問父類的私有變量,但是子類繼承的父類的函數卻可以訪問,不然的話如果只繼承函數而不繼承變量,哪麼父類的函數豈不成了無米之炊了。所以必須把父類的所有變量都繼承下來,這樣既能保護父類的變量也能使用父類的函數。

4.多繼承的構造順序

構造對象的規則需要擴展以控制多重繼承。構造函數按下列順序被調用:

  1. 任何虛擬基類的構造函數按照它們被繼承的順序構造;
  2. 任何非虛擬基類的構造函數按照它們被繼承的順序構造;
  3. 任何成員對象的構造函數按照它們聲明的順序調用;
  4. 類自己的構造函數。

一個有意思的問題:爲什麼析構函數要設置成虛函數

Range *r1 = new Circle(3, 4);

如果析構函數不是虛函數,則r1在釋放內存時,則調用提Range的析構函數。

結果並不是想要的結果,我們想要的結果是調到Circle對象的析構函數。

如果析構函數是虛函數,有多態的支持,r1調用Circle對象的析構函數,Circle對象的析構函數默認調用父類Range的析構函數,保證Circle和Range對象的內容都得到清除。

 

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

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

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

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

重載:函數名相同,函數的參數個數、參數類型或參數順序三者中必須至少有一種不同。函數返回值的類型可以相同,也可以不相同。發生在一個類內部。

重定義:也叫做隱藏,子類重新定義父類中有相同名稱的非虛函數 ( 參數列表可以不同 ) ,指派生類的函數屏蔽了與其同名的基類函數。可以理解成發生在繼承中的重載。

重寫:也叫做覆蓋,一般發生在子類和父類繼承關係之間。子類重新定義父類中有相同名稱和參數的虛函數。(override)

令人迷惑的隱藏規則

本來僅僅區別重載與重寫並不算困難,但是C++的隱藏規則(遮蔽現象)使問題複雜性陡然增加。這裏“隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏。
(2)如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏。
這種隱藏規則,不僅僅是表現在對成員函數上,對同名的data member也是如此。

 

4.4 三種情況怎麼執行:

4.4.1 重載:看參數。

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

4.4.3 覆蓋:調用派生類。

        

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章