天天看點

c++面試常用知識(sizeof計算類的大小,虛拟繼承,重載,隐藏,覆寫)

一. sizeof計算結構體

  注:本機機器字長為64位

1.最普通的類和普通的繼承

  分析:那麼為什麼類(對象)的大小為什麼會是1個位元組呢?那是被編譯器插進去的一個char ,使得這個class的不同實體(object)在記憶體中配置獨一無二的位址。也就是說這個char是用來辨別類的不同對象的。因為如果不是1,當定義這個類的對象數組時候A objects[5]; objects[0]和objects[1]就在同一個位址處,就無法區分。

2.基類中含有私有成員

  分析:基類裡的私有成員在派生類裡仍占有記憶體。在派生類裡,基類的int占4個位元組,char ch[5]占用5個位元組,考慮記憶體的對齊,變成4+(5+3)=12個位元組。

3.類中含有虛函數

  分析:有虛函數的類有個virtual table(虛函數表),裡面包含了類的所有虛函數,類中有個virtual table pointers,通常成為vptr指向這個virtual table,占用8個位元組的大小。成員類Child public繼承于Parent,類Child的虛函數表裡實際上有兩個虛函數Parent::fun()和Child::hjzgg(),類B的大小等于char ch[5]的大小加上一個指向虛函數表指針vptr的大小,考慮記憶體對齊為16。一個類裡若有虛函數,無論有多少個虛函數都隻有一個指向虛表的指針,虛表中的每一個表項儲存着一個虛函數的入口位址。當調用虛函數時,先找到虛表中它對應的表項,找到入口位址再執行。

4.多重繼承

  分析:Child中除了char ch[5]這5個位元組,Child現有一個虛函數表,裡邊有Child自身定義的虛函數以及從Parent中繼承過來的虛函數,然後又另一張虛函數表來存放Father中過來的虛函數,也就是Child對應兩個虛函數表的指針。總共記憶體空間5+8+8=21,考慮記憶體的對齊,為24位元組。

 5.虛繼承

  C++虛拟繼承

  ◇概念:

     C++使用虛拟繼承(Virtual Inheritance),解決從不同途徑繼承來的同名的資料成員在記憶體中有不同的拷貝造成資料不一緻問題,将共同基類設定為虛基類。          這時從不同的路徑繼承過來的同名資料成員在記憶體中就隻有一個拷貝,同一個函數名也隻有一個映射。

  ◇解決問題:

  ◇執行順序

     首先執行虛基類的構造函數,多個虛基類的構造函數按照被繼承的順序構造;

   執行基類的構造函數,多個基類的構造函數按照被繼承的順序構造;

   執行成員對象的構造函數,多個成員對象的構造函數按照申明的順序構造;

   執行派生類自己的構造函數;

     析構以與構造相反的順序執行;

  注:

    從虛基類直接或間接派生的派生類中的構造函數的成員初始化清單中都要列出對虛基類構造函數的調用。但隻有用于建立對象的最派生類的構造函數調用虛基類           的構造函數,而該派生類的所有基類中列出的對虛基類的構造函數的調用在執行中被忽略,進而保證對虛基類子對象隻初始化一次。

    在一個成員初始化清單中同時出現對虛基類和非虛基類構造函數的調用時,虛基類的構造函數先于非虛基類的構造函數執行。

 5.1 沒有用虛拟繼承

    ch.Parent::fun();//這樣調用是對的

    ch.Father::fun();

    分析:因為派生類中的虛函數表會繼承來自各個基類的虛函數。是以Child對應的虛函數表中會有Parent 和 Father各自的fun()函數,是以在調用的時候就會出現歧義,不知道應該調用哪個!

  同樣,和下面一樣的寫法也是錯誤的,增加一個Super類。

 5.2 使用虛拟繼承#include<iostream> 

   Super construction

   Parent construction

   Father construction

   Super fun

   Parent size : 8, Child size : 24

  分析:

二. c++重載、覆寫、隐藏的差別和執行方式

  1.成員函數被重載的特征

  (1)相同的範圍(在同一個類中); 

  (2)函數名字相同; 

  (3)參數不同; 

  (4)virtual 關鍵字可有可無。 

  2.“覆寫”是指派生類函數覆寫基類函數,特征是:

  (1)不同的範圍(分别位于派生類與基類); 

  (3)參數相同; 

  (4)基類函數必須有virtual 關鍵字。 

  3.“隐藏”是指派生類的函數屏蔽了與其同名的基類函數,特征是:

  (1)不同的範圍(分别位于派生類與基類);

  (2)如果派生類的函數與基類的函數同名,但是參數不同,此時,不論有無virtual關鍵字,基類的函數将被隐藏(注意别與重載混淆)。 

  (3)如果派生類的函數與基類的函數同名,且參數相同,但是基類函數沒有virtual 關鍵字。此時,基類的函數被隐藏(注意别與覆寫混淆)。

  小結:說白了就是如果派生類和基類的函數名和參數都相同,屬于覆寫,這是可以了解的吧,完全一樣當然要覆寫了;如果隻是函數名相同,參數并不相同,則屬 于隐藏。

繼續閱讀