不同型別的指標

Andy Niu發表於2013-12-18

1、思考,不同型別的指標,到底有什麼區別?

  指向Animal的指標和指向Dog的指標,到底有什麼區別?首先,指標的表示方法相同,指標的內容相同,都是一個int,表示地址。區別只是指向物件的型別不同(好像是廢話)。這有什麼意義呢? 這其實是告訴了編譯器如何解釋這個地址中的記憶體內容以及大小。也就是說,對於指向Animal 的指標,編譯器把指向內容當作一個Animal,對於指向Dog 指標,編譯器把指向的內容當作Dog。

2、那麼,問題來了,Animal* pa = new Dog(),是怎麼做到執行期多型的呢?

  pa的表面型別是Animal,真實型別是Dog,編譯器在編譯時只知道pa的表面型別,那麼把pa當作Animal來解釋,能不能做到執行時多型呢?簡單回憶一下,Animal對應一個虛方法表(虛方法表可認為一個陣列,元素是方法指標),Dog對應一個虛方法表,可以認為Dog中的虛方法表是整體拷貝了Animal 的虛方法表,對於重寫的方法在對應的位置換上重寫後的方法,對於新增的虛方法,加在虛方法表的最後。物件的記憶體中只有例項欄位和vptr,vptr指向vtbl(虛方法表),根據對應的方法,在vtbl對應的位置上,找到方法指標,進而找到方法。

  對於Animal物件和Dog物件,可認為在相同位置都放著vptr。這樣的話,pa指向記憶體中的一個Dog物件,我把指向的內容當作Animal來解釋,也能找到vptr,但是這個vptr指向Dog類的虛方法表。由於Dog類中虛方法表,是在Animal虛方法表的基礎上,進行了替換,這就構成了執行時多型。

3、現在考慮,Animal和Dog都有一個Name欄位,pa->Name 訪問是Animal的欄位,還是Dog 的欄位呢?  

  Animal物件和Dog物件的記憶體分佈,舉例來說,Animal物件為:age,Name,vptr,那麼Dog物件的記憶體分佈就是age,Name,vptr,Name。前面Name的作用域是父類,後面Name的作用域是子類,子類作用域小於父類作用域。

  編譯器把pa指向的內容,當作Animal來解釋,取的是Animal的欄位。如果想要取出Dog 的Name欄位怎麼辦呢?當然是,告訴編譯器,把pa指向的內容當作Dog來解釋,強制型別轉化為Dog指標。

相關文章