在上篇文章《戳我》中涯捻,簡(jiǎn)單說(shuō)了繼承的三種分類:?jiǎn)卫^承多律、多重繼承酥馍、重復(fù)繼承逗鸣。
一般的如果沒(méi)有虛函數(shù)贞让,那對(duì)象的內(nèi)存布局就如我們看到的一樣乍构,定義了幾個(gè)變量根據(jù)字節(jié)對(duì)齊就能算出其在內(nèi)存中所占字節(jié)大小甜无。但是有了虛函數(shù),就不同了哥遮,因?yàn)橛辛颂摵瘮?shù)就意味著存在虛函數(shù)指針岂丘,那指針我們知道是占四個(gè)字節(jié)(32位)的,所以從本篇文章開(kāi)始來(lái)分析存在虛函數(shù)時(shí)對(duì)象的內(nèi)存布局是怎么樣的眠饮?(版本是Visual Studio2012)
對(duì)于單繼承:
寫(xiě)出以下代碼:
class Father
{
public:
Father(int data1):fa(data1){}
virtual void f(){cout<<"Father::f()"<<" ";}
virtual void ff(){cout<<"Father::ff()"<<" ";}
virtual void fff(){cout<<"Father::fff()"<<" ";}
protected:
int fa;
};
class Son:public Father
{
public:
Son(int data):sa(data),Father(data){}
virtual void f(){cout<<"Son::f()"<<" ";}
virtual void ss(){cout<<"Son::ss()"<<" ";}
virtual void sss(){cout<<"Son::sss()"<<" ";}
protected:
int sa;
};
class Grandson:public Son
{
public:
Grandson(int data):ga(data),Son(data){}
virtual void f(){cout<<"Grandson::f()"<<" ";}
virtual void ss(){cout<<"Grandson::ss()"<<" ";}
virtual void ggg(){cout<<"Grandson::ggg()"<<" ";}
protected:
int ga;
};
typedef void (*Function)(void);//函數(shù)指針
int main()
{
//main函數(shù)主要進(jìn)行打印
Grandson *pgs=new Grandson(12);
Function pFun=NULL;//定義一個(gè)函數(shù)指針
cout<<"[0] _vfptr"<<endl;
for(int i=0;i<6;++i)
{
pFun=((Function*)(long**)(*(long*)(pgs)))[i];
cout<<" "<<"["<<i<<"]"<<" ";
pFun();
cout<<((long**)(*(long*)pgs))[i]<<endl;
}
cout<<"[1] "<<((long*)pgs)[1]<<endl;
cout<<"[2] "<<((long*)pgs)[2]<<endl;
cout<<"[3] "<<((long*)pgs)[3]<<endl;
delete pgs;
return 0;
}
注:
(long*)(pgs):將pgs強(qiáng)轉(zhuǎn)成long*
(*(long*)(pgs)):解引用奥帘,虛函數(shù)表的地址
(long**)(*(long*)(pgs)):虛函數(shù)表的地址強(qiáng)轉(zhuǎn)成二級(jí)指針
查看Grandson類生成對(duì)象的內(nèi)存布局:(點(diǎn)擊【項(xiàng)目】-》【屬性】-》【C/C++】-》【命令行】-》在其它選項(xiàng)處寫(xiě)上
【/d1 reportSingleClassLayoutGrandson】-》點(diǎn)擊【確定】就好了 )
可以看出:
1、子類繼承了父類的成員變量仪召,成員函數(shù)不占空間寨蹋。
2、有虛函數(shù)時(shí)出現(xiàn)了一個(gè)vfptr指針扔茅,并把該指針?lè)旁诹藘?nèi)存的開(kāi)始處(相對(duì)對(duì)象偏移為0)钥庇。
3、同名的函數(shù)在虛表中被覆蓋咖摹。
4评姨、同時(shí)也看到了有一張?zhí)摫淼拇嬖冢摫碇袕?號(hào)下標(biāo)開(kāi)始就存放的是虛函數(shù)萤晴,有一個(gè)問(wèn)題就是從虛表中也能看出有RTTI信息(&Grandson_meta)和vfptr相對(duì)于類型的偏移信息(0)吐句,但它不在0號(hào)下標(biāo)鎖對(duì)應(yīng)的位置,那它在哪店读?怎么打印出來(lái)嗦枢?看到的寶寶希望能幫我解答。
將上面程序進(jìn)行打印及調(diào)試屯断,可以看到:
現(xiàn)在文虏,我們來(lái)畫(huà)出單繼承下Grandson類的內(nèi)存布局: