1. 程式人生 > >c++虛函數實現與this指針

c++虛函數實現與this指針

ive 我們 構造 public 註意 col 入口 一個 成員

我們知道當我們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指針