c++虛函數實現與this指針
我們知道當我們sizeof 一個類的時候,類的成員函數是不計算在對象的大小的裏的,這是為什麽呢?因為類的成員函數不是屬於某一個對象的,而是類的所有對象所共享的,就像static變量那樣。如果虛函數和普通成員函數一樣,那麽我們就不能通過指向子類的基類指針來引用子類的方法了,因為我們將不知道調用哪個方法,多態就無從談起。那麽多態是怎麽實現的呢?
- 虛函數、虛指針與虛表
我們可以做一個小實驗
class A{ public: int a; virtual void myfun(){} }; class B:public A{ public: int b; }; B obj_b;
obj_b.a=1;
obj_b.b=2; A *p=&B; cout<<p<<endl; cout<<&(p->a)<<endl;
cout<<p->a<<‘\t‘<<*(&(p->a)+1)<<endl;
p的值和&(p->a)的值是相差4個字節的,最後一行輸出的值為1 ,2。我們可以推斷出obj_b在內存中的分布是首先一個占有4字節的某類型,然後是int a,最後是int b。
初始的4字節其實就是虛指針。
而類A的對象在內存的分布其實是虛指針然後是int a。
如果類B繼承A,在B構造的時候,會繼承虛指針和int a,但是虛指針指向的虛表就不同了。若在B中實現了虛函數則虛表中的對應函數的入口地址也會改變。從而達到多態的目的。
註意指針p並訪問不到b,因為p是A類型的指針,可見指針的訪問範圍由的類型決定了。所以我們通過&(p->a)+1來訪問b。
那麽多重繼承時是什麽情況呢?
多重繼承的時候,對於每個有虛函數的基類,子類都會繼承相應的虛指針並改寫虛表。
- this指針
我覺得一篇blog寫的挺好就引用過來了。博客地址為:http://www.cnblogs.com/CCQLegend/p/3270738.html
this指針跟不少人想象的不一樣,它的類型由被調用函數決定。它的類型遵循著這兩點規則:(途中打勾為首地址。)
1.對於非虛函數,this指針的基準地址為函數定義所在層級對象的首地址,範圍為該層級對象始末。
如:IA::FF();
this指針類型是以D0H為首地址,範圍是從首地址開始到DFH為止。(其實裏面有內存空洞,我們不去糾結這個)
Derived::FF();
this指針類型是C0H為首地址,範圍是從首地址到E8H為止。
2.對於虛函數,this指針的基準地址為函數首先聲明者的首地址,範圍為實現者的始末。
如:IA::F();
其this指針類型是以D0H為首地址,範圍是從首地址開始到DFH為止。
Derived::F();
其this指針類型是以D0H為首地址,範圍是從C0H到E8H為止。
那麽當有IA* a=new Derived();後,
a->F();便是這麽訪問b成員的了。假設首地址D0H保存在寄存器rax裏,
rax-8
c++虛函數實現與this指針