c++多重繼承和虛繼承及虛函數深入理解

來源:互聯網
上載者:User
 先看一例子:  class   base  
  {  
  public:  
  virtual   void   f()   const   {};  
  };  
   
  class   d1   :   virtual   public   base  
  {};  
   
  class   d2   :   virtual   public   base    
  {};  
   
  class   derived   :   public   d1,   public   d2  
  {};  
using namespace std;   
  int   main()  
  {  
  d1   b;  
  d2   c;  
  derived   d;  
  cout<<sizeof(b)<<endl;  
  cout<<sizeof(c)<<endl;  
  cout<<sizeof(d)<<endl;  
  return   0;  
  }    結果是 8, 8 12.先說class Base吧,它有一個虛函數,且沒有父類,所以只有一個指標大小,也就是4BYTES了.至於d1和d2就不那麼簡單了,它不僅有虛函數而且是虛繼承.要複雜一些了.D1之所以為8是由於它有兩個表指標組成的.一個PVBTBL,一個是PVFTBL.PVBTBL是指虛基類表指標,一個類可以有0-n個VBTBL(VIRTUAL BASE CLASS TABLE),在這裡只有一個,不過很快就會看到有兩個VBTBL的類了。PVFTBL是指虛函數表指標了,一個類可以有 0-N個VFTBL(VIRTUAL FUNCTION TABLE),在這裡也只有一個。我們看一看D1的布局吧。D1---------------PVBTBL        ---------------------》指向一個虛基類表。--------------PVFTBL        ---------------------》指向一個虛函數表。--------------所以其大小就為8了。再說說其初始化過程。我們知道任何一個類的虛基類的建構函式是最先被調用。最開如,編譯器會把d1::vbtbl的指標表放在圖中PVBTBL的地方,此時THIS指標也指向PVBTBL,然後調整THIS指標令其指向PVFTBL,並調用BASE::BASE();BASE()會在PVFTBL的地方放上OFFSET BASE::VFTBL,由於它沒有資料成員要初始化,所以它就返回了。呵呵,很不幸,它很快就要被D1::的VFTBL所代替了,這也正是為什麼C++會根據實際對象的類型所進行正確行為的原因。不過,這裡的替代有點兒特別。它先查看,VBTABL(其中第二項為虛基類的位移[PVBTABL+4]),找到虛基類的位移量,然後再加上THIS指標的值,些時它正好指向PVFTBL,它就用D1::VFTBL替代了虛基類的虛函數表了。 上邊提到有的類會有兩個虛基表,-DEPRIVED類就是這種情況了。它的初始化比上面所說的更複雜。先看布局也再說吧----------PVBTBL  ------》同上----------PVBTBL  ------》同上----------PVFTBL--------》同上----------PVFTBL--------》同上。---------------------很明顯可以看到它有兩個虛基類表,ONE FOR D1,ANOTHER FOR D2。虛基類表的個數取決於當前的繼承方式及其基類的情況。在這裡可以看到,它的基類D1,D2都有虛繼承的情況,所以這裡就有兩個虛基類表了。INIT:在這裡編譯器會先準備兩個VBTBL,然後,當初始化時(也就是調用CONSTRUCTOR時),兩個VBTBL分別放到相應的位置,然後調整THIS指標的值,THIS+8,POINTING TO THE FIRST PVFTBL的位置,然後調用BASE::BASE(),可以看到的確是虛基類的建構函式是最先調用的。它會把它的OFFSET BASE::VFTBL,放到this + 8 的位置,沒有其它要初始化的成員,SO,RETURN TO THE CALLER。THEN THIS= THIS -8,INVOKE THE D1::D1(),ENTER THE D1::D1(),FIRSTLY ,IT LOOKS UP THE VBTBL POINTED BY FIRST PVTBL FOR THE OFFSET THE ITSELF,,然後,修改THIS的值,令其指向,SUBOBJECT OF D1 ,由於這裡也沒有成員,所以初始化也很簡單,它只是用它自己的虛函數替代上面有BASE::BASE()所放置的虛函數表,然後,返回。至於後面的D2,也和這裡類似,不過THIS指標所指的位置不同,它指向中的最後一個位置。終於到最後一步了,DEPRIVED會用它自己的虛函數表去替代原來已有的。。。。。(反正自己看,不用說太清了。)下面還有更好玩的。一個類可能會有多個虛函數表,且不同的。看這個例子。#include "stdafx.h"
#include <string.h>
class Base1
{
public: 
 virtual void Base1Test() {printf("this is from Base1 virtual function /n");}
 int a;};class Base2
{
public:
 virtual void Base2Test() {printf("this is from the Base2 virtual function/n");}
 int b;
};class Deprived : public virtual Base1, public Base2
{
public:
 int d;
};Base1 * base1;
Base2 *base2;
void f()
{Deprived deprived;base1 = &deprived;
base2 = &deprived;base1->Base1Test();base2->Base2Test();deprived.a = 16;
deprived.b = 32;
deprived.d = 48;return;}
int main(int argc, char* argv[])
{ printf("sizeof(Deprived):%d/n", sizeof(Deprived)); f();
 
 return 0;
}NOTE:本例中,只有一個VBTBL,呵呵,由於DEPRIVED VIRTURE INHERITS THE BASE1,但是它卻有多個虛函數表。ONE FOR BASE1, ANOTHER FOR BASE2。它的記憶體布局和上面有較大變化了。如下所示。DEPRIVE ----------------                       BASE2 PARTY  =========》  INCLUDE 一個虛函數表指標及int b(它就是BASE2的成員變數。----------------VBTBL PARTY  ==========》就是一個指向虛基類表的指標了。不用多說了。-----------------DEPRIVE PARTY ==========》這裡僅有一個DEPRIVED的成員變數d,它和BASE2共用一個虛函數表指標。所以就只有一個成員變數D了。-----------------VIRTUAL BASE PARTY -=======》也就是BASE1 PARTY了。它結構如下。                                                  ===========                                                  PVFTBL      --------------》BASE1的VIRTUAL FUNC TBL                                                 =============------------------------------- 理所當然它會所調用BASE1的CONSTRUCTOR,(FOR THE VIRTUAL BASE REASON。。。。),,然後正常初始化,不過到了最後,會比較獨特,DPRIVED CLASS有兩個VIRTUAL TABLE。一個是為BASE1準備的,一個是為BASE2準備的。也正是為什麼可以用基類的指標正確的調用子類的VIRTURL FUNCTION的原因。。。。。更詳細,就不說了,反正是自己看。呵呵。

 

聯繫我們

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