日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++虚继承(十) --- 谈谈陈皓遗留的问题

發(fā)布時(shí)間:2024/4/11 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++虚继承(十) --- 谈谈陈皓遗留的问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

網(wǎng)上關(guān)于c++對(duì)象布局的文章挺多,而且《深度探索c++對(duì)象模型》(Inside The C++ Object Model?侯捷?譯)一書(shū)中也很詳細(xì)地介紹。如果你一點(diǎn)都不了解C++對(duì)象的布局,我推薦你看看《深度探索c++對(duì)象模型》的第三章,如果你意猶未盡下面的兩個(gè)系列都很不錯(cuò):

一是陳皓的《C++?對(duì)象的內(nèi)存布局》圖文并貌,寫(xiě)得很是詳細(xì)。地址是http://blog.csdn.net/haoel/archive/2008/10/15/3081328.aspx。

二是玄機(jī)逸士的《對(duì)象內(nèi)存布局》系列則幾乎把每種可能性列出來(lái)了,尤為詳盡。地址是http://blog.csdn.net/pathuang68/archive/2009/04/23/4101970.aspx。

讀了以上好文,對(duì)于c++對(duì)象的布局其實(shí)應(yīng)該是山水了然于胸了,不過(guò)我最在寫(xiě)一個(gè)用c++模仿C#事件機(jī)制的東東,但發(fā)覺(jué)得有很幾處細(xì)節(jié)不是很明了,而且陳皓朋友也在最后提出了一個(gè)問(wèn)題,雖然有網(wǎng)友答之,仍語(yǔ)言不詳。而我卻必需深入了解此,才能真正實(shí)做出C++的事件。

此文應(yīng)該算是狗尾續(xù)貂之作,高手可能會(huì)不屑一顧。不過(guò)希望還是對(duì)一些朋友有幫助。因?yàn)閷?duì)于普通類(lèi)的對(duì)象布局,前人備述已,我也不太可能寫(xiě)出什么新意來(lái),更多的是因?yàn)槲冶容^懶。呵呵,本文所探討的就是那種極端復(fù)雜的菱形結(jié)構(gòu)如下:

class A ;

class B : virtual public A;

class C : virtual public B;

class D : public B,public C;

?

??? 好了,來(lái)了,我們從最基礎(chǔ)的的討論起。當(dāng)c++支持virtual base class?時(shí),就會(huì)多了一些額外負(fù)擔(dān),當(dāng)class中內(nèi)含一個(gè)或多個(gè)virtual base class subobject時(shí),將分成兩個(gè)部分,一個(gè)不變局部和一個(gè)共享局部。最初的方案是為每一個(gè)虛基類(lèi)安插一個(gè)指針指向這個(gè)虛基類(lèi),其缺點(diǎn)是為了負(fù)擔(dān)太重,而且當(dāng)虛繼承鏈加長(zhǎng)時(shí),導(dǎo)致間接存取時(shí)間加長(zhǎng)(需通過(guò)多次跳轉(zhuǎn))。因此有兩種解決方案(《深入》一書(shū)中所提):

一、是引入virtual base class table,不管多少個(gè)虛基類(lèi),總是只有一個(gè)指針指向它,這個(gè)virtual base class table(VBTBL)包括真正的?virtual base class?指針。

二、Bjarne的辦法是在virtual function table中放置virtual base class的offset,而非地址,這個(gè)offset在virtual function table?的負(fù)位置(正值是索引virtual function,而負(fù)值則方向盤(pán)引到virtual base class offsets)。

我用vc2003觀(guān)測(cè)到的實(shí)際情況是。在類(lèi)中增加一個(gè)指針(VBPTR)指向一個(gè)VBTBL,這個(gè)VBTBL的第一項(xiàng)記載的是從VBPTR?與本類(lèi)的偏移地址,如果本類(lèi)有虛函數(shù),那么第一項(xiàng)是FF FF FF FC(也就是-4),如果沒(méi)有則是零,第二項(xiàng)起是VBPTR與本類(lèi)的虛基類(lèi)的偏移值。vc2003的這種方案?jìng)€(gè)人覺(jué)得沒(méi)有Bjarne的好,一是要多一個(gè)指針,二是因?yàn)閂BPTR與虛函數(shù)表分開(kāi)設(shè)計(jì),也不便于修改。至于其它編譯器,因?yàn)槲腋渌幾g器不熟,所以也就沒(méi)有實(shí)測(cè)它們。

下面給出對(duì)于類(lèi)定義

struct B1

{

????int a;

????int b;

};

struct B2

{

????virtual void foo(void);

????int c;

????int d;

};

?

struct Test : virtual public B1, virtual public B2

{

????virtual void func1(void);

????virtual void func2(void);

????virtual void func3(void);

????int X;

};

一個(gè)Test?對(duì)象的內(nèi)存布局圖,我們可以清楚的看到在VS2003中VBPTR以及VBTBL的結(jié)構(gòu)以及其相關(guān)的內(nèi)容是什么意義。以及Bjarne的方案的優(yōu)點(diǎn)。

?

?

最后我們來(lái)看一個(gè)完整的例子以及內(nèi)存結(jié)構(gòu)布局。圖后有相關(guān)代碼。

?

?

代碼如下:

struct?A

{

????A(int?v=100):X(v){};

????virtual?void?foo(void){}

????int?X;

};

?

struct?B :virtual?public?A

{

????B(int?v=10):Y(v),A(100){};

????virtual?void?fooB(void){}

????int?Y;

};

?

struct?C :?virtual?public?A

{

????C(int?v=20):Z(v),A(100){}

????virtual?void?fooC(void){}

????int?Z;

};

?

?

struct?D :?public?B,?public?C

{

????D(int?v =40):B(10),C(20),A(100),L(v){}

????virtual?void?fooD(void){}

????int?L;

};

?

?

int?_tmain(int?argc, _TCHAR* argv[])

{

???

????A a;

????int?*ptr;

????ptr = (int*)&a;

????cout << ptr << " sizeof = " <<?sizeof(a) <<endl;

????for(int?i=0;i<sizeof(A)/sizeof(int);i++)

????{

????????if(ptr[i] < 10000)

????????{

?????????????cout << dec << ptr[i]<<endl;

????????}

????????else?cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;

????}

?

????cout << "--------------------------------------" <<endl;

?

????B b;

????ptr = (int*)&b;

????cout <<"addr:" << ptr << " sizeof = " <<?sizeof(b) <<endl;

????for(int?i=0;i<sizeof(B)/sizeof(int);i++)

????{

????????if(ptr[i] < 10000)

????????{

?????????????cout << dec << ptr[i]<<endl;

????????}

????????else?cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;

????}

?

????cout << "--------------------------------------" <<endl;

???

????D d;

????ptr = (int*)&d;

????cout <<"addr:" << ptr << " sizeof = " <<?sizeof(d) <<endl;

????for(int?i=0;i<sizeof(D)/sizeof(int);i++)

????{

????????if(ptr[i] < 10000)

????????{

?????????????cout << dec << ptr[i]<<endl;

????????}

????????else?cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;

????}

????return?0;

}

總結(jié)

以上是生活随笔為你收集整理的C++虚继承(十) --- 谈谈陈皓遗留的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。