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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM