在《深度探索c++物件模型》裡,有乙個問題,也是去公司面試的時候那些技術人員常問的問題:在c++中,obj是乙個類的物件,p是指向obj的指標,該類裡面有個資料成員mem,請問obj.mem和p->mem在實現和效率上有什麼不同。
答案是:只有一種情況下才有重大差異,該情況必須滿足以下3個條件:
(1)、obj 是乙個虛擬繼承的派生類的物件
(2)、mem是從虛擬基類派生下來的成員
(3)、p是基類型別的指標
當這種情況下,p->mem會比obj.mem多了兩個中間層。(也就是說在這種情況下,p->mem比obj.mem要明顯的慢,呵呵)
why?
如果好奇心比較重的話,請往下看 :)
1、虛基類的使用,和為多型而實現的虛函式不同,是為了解決多重繼承的二義性問題。
舉例如下:
class a ;
class b : virtual public a ;
class c :virtual public a ;
class d : public b, public c ;
上面這種菱形的繼承體系中,如果沒有virtual繼承,那麼d中就有兩個a的成員int a;繼承下來,使用的時候,就會有很多二義性。而加了virtual繼承,在d中就只有a的成員int a;的乙份拷貝,該拷貝不是來自b,也不是來自c,而是乙份單獨的拷貝,那麼,編譯器是怎麼實現的呢??
在回答這個問題之前,先想一下,sizeof(a),sizeof(b),sizeof(c),sizeof(d)是多少?(在32位x86的linux2.6下面,或者在vc2005下面)
在linux2.6下面,結果如下:sizeof(a) = 4; sizeof(b) = 12; sizeof(c) = 12; sizeof(d) = 24
sizeof(b)為什麼是12呢,那是因為多了乙個指標(這一點和虛函式的實現一樣),那個指標是幹嘛的呢?
那麼sizeof(d)為什麼是24呢?那是因為除了繼承b中的b,c中的c,a中的a,和d自己的成員d之外,還繼承了b,c多出來的2個指標(b和c分別有乙個)。再強調一遍,d中的int a不是來自b也不是來自c,而是另外的乙份從a直接靠過來的成員。
如果宣告了d的物件d: d d;
那麼d的記憶體布局如下:
vb_ptr: 繼承自b的指標
int b: 繼承自b公有成員
vc_ptr:繼承自c的指標
int c: 繼承自c的共有成員
int d: d自己的公有成員
int a: 繼承自a的公有成員
那麼以下的用法會發生什麼事呢?
d dd;
b *pb = ⅆ
pb->a;
上面說過,dd中的int a不是繼承自b的,也不是繼承自c的,那麼這個b中的pb->a又會怎麼知道指向的是dd記憶體中的第六項呢?
那就是指標vb_ptr的妙用了。原理如下:(其實g++3.4.3的實現更加複雜,我不知道是出於什麼考慮,而我這裡只說原理,所以把過程和內容簡單化了)
首先,找到vb_ptr(這個不用找,因為在g++中,vb_ptr就是b*中的第一項,呵呵),然後取得vb_ptr指向的位址的內容(這個例子是20),最後把這個內容與指標pb相加,就得到pb->a的位址了。
所以說這種時候,用指標轉換多了兩個中間層才能找到基類的成員,而且是執行期間。
由此也可以推知dd中的vb_ptr和vc_ptr的內容都是一樣的,都是指向同乙個位址,該位址就放20(在本例中)
如下的語句呢:
a *pa = ⅆ
pa->a = 4;
這個語句不用轉換了,因為編譯器在編譯期間就知道他把a中的成員插在dd中的那個地方了(在本例中是末尾),所以這個語句中的執行效率和dd.a是一樣的(至少也是差不多的)
這就是虛基類實現的基本原理。
注意的是:那些指標的位置和基類成員在派生類成員中的記憶體布局是不確定的,也就是說標準裡面沒有規定int a必須要放在最後,只不過g++編譯器的實現而已。c++標準大概只規定了這套機制的原理,至於具體的實現,比如各成員的排放順序和優化,由各個編譯器廠商自己定~
C 虛基類的實現機制
在 深度探索c 物件模型 裡,有乙個問題,也是去公司面試的時候那些技術人員常問的問題 在c 中,obj是乙個類的物件,p是指向obj的指標,該類裡面有個資料成員mem,請問obj.mem和p mem在實現和效率上有什麼不同。答案是 只有一種情況下才有重大差異,該情況必須滿足以下3個條件 1 obj ...
C 虛基類的實現機制
在 深度探索c 物件模型 裡,有乙個問題,也是去公司面試的時候那些技術人員常問的問題 在c 中,obj是乙個類的物件,p是指向obj的指標,該類裡面有個資料成員mem,請問obj.mem和p mem在實現和效率上有什麼不同。答案是 只有一種情況下才有重大差異,該情況必須滿足以下3個條件 1 obj ...
C 虛基類的實現機制 筆記
在 深度探索c 物件模型 裡,有乙個問題,也是去公司面試的時候那些技術人員常問的問題 在c 中,obj是乙個類的物件,p是指向obj的指標,該類裡面有個資料成員mem,請問obj.mem和p mem在實現和效率上有什麼不同。答案是 只有一種情況下才有重大差異,該情況必須滿足以下3個條件 1 obj ...