《深度探索c++對象模型》(一)

前述

看完《深度探索c++對象模型》冯袍,心中對c++編譯器在編譯期間所做的處理有了更深入的認識,我想碾牌,除了對編譯器本身有深入認識的作者之外康愤,應(yīng)該很少有人對c++的對象模型有這么深的認識。能接觸了這本書舶吗,是我們的幸運征冷,是作者讓我們有機會能一窺其貌,感謝作者誓琼。
其實第一遍讀這本書检激,我的收獲還不算多,這可能是我對c++的使用還不夠多的緣故腹侣,但通過這本書叔收,我以后使用c++的時候,就會心里有更多的底氣傲隶,也會有更多需要注意的地方饺律,在經(jīng)過更多的實踐之后,我一定還會回來拜讀這本書的跺株。
現(xiàn)在复濒,我想就本書所學(xué)到的的知識做一些總結(jié)。


參考書籍及鏈接:
《深度探索c++對象模型》
https://www.cnblogs.com/lengender-12/p/6944042.html


一帖鸦、關(guān)于對象

1. C++在加入封裝后(只含有數(shù)據(jù)成員和普通成員函數(shù))的布局成本增加了多少芝薇?

答案是并沒有增加布局成本。就像C struct一樣作儿,memeber functions雖然含在class的聲明之內(nèi)洛二,卻不出現(xiàn)在object中。每一個non-inline member function只會誕生一個函數(shù)實體攻锰。至于每一個“擁有零個或一個定義的” inline function則會在其每一個使用者(模塊)身上產(chǎn)生一個函數(shù)實體晾嘶。

2. C++在布局以及存取時間上主要的額外負擔(dān)是由virtual引起的,包括:

virtual funciton機制娶吞,用以支持一個有效率的“執(zhí)行期綁定”
virtual base class垒迂,用以實現(xiàn)“多次出現(xiàn)在繼承體系中的base class,有一個單一而被共享的實體”

二妒蛇、C++ 對象模式(The C++ Object Model)

1. 在C++中机断,有兩種class data members:static 和 nonstatic楷拳,以及三種class member functions:static、nonstatic和virtual吏奸。

2. C++對象模型中欢揖,nonstatic data members被配置于每一個class object之內(nèi)。

static data members則被存放在所有的class object之外奋蔚。static和nonstatic function members也被放在所有的class object之外她混。virtual function則以兩個步驟支持之:

    1. 每個class產(chǎn)生出一堆指向virtual functions的指針,放在表格之中泊碑。這個表格被稱為virtual table(vtbl)
    1. 每一個class object被安插一個指針坤按,指向相關(guān)的virtual table。通常這個指針被稱為vptr馒过。vptr的設(shè)定和重置都由每一個class的constructor臭脓、destructor和copy assignment運算符自動完成。每一個class所關(guān)聯(lián)的type_info object(用以支持runtime type identification, RTTI)也經(jīng)由virtual table被指出來沉桌,通常放在表格的第一個slot處膳殷。

這個模型的主要優(yōu)點在于它的空間和存取時間的效率鸠信。
主要缺點是:如果應(yīng)用程序代碼未曾改變,但所用到的class objects的nonstatic data members有所修改(有可能是增加、移除或更改)呆盖,那么應(yīng)用程序代碼同樣得重新編譯血淌。

3.繼承關(guān)系可以指定為虛擬(virtual判呕,也就是共享的意思):

在虛擬繼承的情況下品嚣,base class不管在繼承鏈中被派生(derived)多少次,永遠只會存在一個實例(稱為subobject)求冷。

三瘤运、關(guān)鍵詞帶來的差異

1.什么時候一個人應(yīng)該在c++程序中以struct取代class?

答案之一是當(dāng)他讓人感覺比較好的時候。單獨來看匠题,關(guān)鍵詞本身并不提供任何差異拯坟,c++編譯器對二者都提供了相同支持,我們可以認為支持struct只是為了方便將c程序遷移到c++中韭山。
88

2.那為什么我們要引入class關(guān)鍵詞郁季?

這是因為引入的不只是class這個關(guān)鍵詞,更多的是它所支持的封裝和繼承的哲學(xué)钱磅。

3.怎么在c++中用好struct梦裂?

將struct和class組合起來,組合盖淡,而非繼承年柠,才是把c和c++結(jié)合在一起的唯一可行的方法。另外褪迟,當(dāng)你要傳遞“一個復(fù)雜的class object的全部或部分”到某個c函數(shù)去時冗恨,struct聲明可以將數(shù)據(jù)封裝起來答憔,并保證擁有與c兼容的空間布局。

四掀抹、對象的差異

1. C++程序設(shè)計模型直接支持三種程序設(shè)計典范(programming paradigms):

  • 程序模型:數(shù)據(jù)和函數(shù)分開攀唯。
  • 抽象數(shù)據(jù)類型模型:數(shù)據(jù)和函數(shù)一起封裝以來提供。
  • 面向?qū)ο竽P停嚎赏ㄟ^一個抽象的base class封裝起來渴丸,用以提供共同接口,需要付出的就是額外的間接性另凌。

雖然你可以直接或間接處理繼承體系中的一個base class object,但只有通過pointer或reference的間接處理谱轨,才支持OO程序設(shè)計所需的多態(tài)性質(zhì)。c++通過class的pointers和reference來支持多態(tài)吠谢,這種程序設(shè)計風(fēng)格就稱為面向?qū)ο?/strong>

Liberary_materials thing1;//基類
Book book;//派生類
thing1=book;
thing1.check_in();//這種情況下土童,調(diào)用的是基類的check_in()
Liberary_materials &thing2=book
thing2.check_in();//這種情況下調(diào)用的才是book的check_in()

2. C++以下列方法支持多態(tài):

    1. 經(jīng)由一組隱式的轉(zhuǎn)化操作。例如把一個derived class指針轉(zhuǎn)化為一個指向其public base type的指針
         shape *ps=new circle();
    1. 經(jīng)由virtual function機制
         ps->rotate();
    1. 經(jīng)由dynamic_cast和typeid運算符
         if(circle *pc=dynamic_cast<circle *>(ps))...

多態(tài)的主要用途是經(jīng)由一個共同的接口來影響類型的封裝工坊,這個接口通常被定義在一個抽象的base class中献汗。這個共享接口是以virtual function機制引發(fā)的,它可以在執(zhí)行期根據(jù)object的真正類型解析出到底是哪一個函數(shù)實體被調(diào)用王污。

3. 需要多少內(nèi)存才能表現(xiàn)一個class object?

  • 其nonstatic data members的總和大小
  • 加上任何由于aliginment的需求而填補上去的空間(可能存在于members之間罢吃,也可能存在于集合體邊界),aliginement就是將數(shù)值調(diào)整到某數(shù)的倍數(shù),如在32位的計算機上為4昭齐。
  • 加上為了支持virtual而由內(nèi)部產(chǎn)生的任何額外負擔(dān)

4. 一個指針(引用)尿招,不管它指向哪一種數(shù)據(jù)結(jié)構(gòu),指針本身所需的內(nèi)存大小是固定的(一個機器字)阱驾。

例如:一個指向ZooAnimal的指針是如何地與一個指向整數(shù)得指針或一個指向template Array的指針有所不同的呢就谜?

ZooAnimal *px;
int *pi;
Array<string> *pta;

以內(nèi)存需求的觀點來說,沒有什么不同里覆!它們?nèi)齻€都需要足夠的內(nèi)存來放置一個機器地址(通常是個word)丧荐。“指向不同類型的各指針”間的差異,既不在其指針表示法不同喧枷,也不在其內(nèi)容(代表一個地址)不同虹统,而是在其所尋址出來的object類型不同,也就是說割去,“指針類型”會教導(dǎo)編譯器如何解釋某個特定地址中的內(nèi)存內(nèi)容及其大小窟却。

5.轉(zhuǎn)型(cast)其實是一種編譯器指令。

大部分情況下它并不改變一個指針?biāo)恼嬲刂飞肽妫挥绊憽氨恢赋鲋畠?nèi)存大大小和其內(nèi)容”的解釋方式夸赫。

如一個類型為void *的指針只能夠持有一個地址,但不能 通過它操作所指object咖城。

6.一個基類指針和其派生類指針有什么不同茬腿?(單一一層繼承呼奢,且其都指向派生類對象)

二者都指向基類對象的第一個byte,其間的差別是,派生類指針涵蓋的地址包含整個派生類對象切平,而一個基類指針?biāo)w的地址只包含派生類對象的基類子對象部分握础。

但基類指針可以通過virtual機制訪問派生類對象的函數(shù)。

7.當(dāng)一個base class object被直接初始化為(或被指定為)一個derived class object時悴品。

derived object就會被切割(sliced)以塞入較小的base type內(nèi)存中禀综,derived type將沒有留下任何蛛絲馬跡。多態(tài)于是不再呈現(xiàn)苔严,而一個嚴(yán)格的編譯器可以在編譯器解析一個“通過此object而觸發(fā)的virtual function調(diào)用操作”定枷,因而回避virtual機制。如果virtual function被定義為inline届氢,則更有效率上的大收獲欠窒。

8.C++也支持具體的ADT程序風(fēng)格,如今被稱為object-based(OB)退子。

一個OB設(shè)計可能比一個對等的OO設(shè)計速度更快而且空間更緊湊岖妄。速度快是因為所有的函數(shù)調(diào)用操作都在編譯時期解析完成,對象構(gòu)建起來時不需要設(shè)置virtual機制寂祥〖雠埃空間緊湊是因為每一個class object不需要負擔(dān)傳統(tǒng)上為了支持virtual機制兒需要的額外負荷。不過丸凭,OB設(shè)計比較沒有彈性缚俏。
在彈性(OO)和(OB)之間常常存在著取舍。一個人能夠有效選擇其一之前贮乳,必須先清楚了解兩者的行為和應(yīng)用領(lǐng)域的需求忧换。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市向拆,隨后出現(xiàn)的幾起案子亚茬,更是在濱河造成了極大的恐慌,老刑警劉巖浓恳,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刹缝,死亡現(xiàn)場離奇詭異,居然都是意外死亡颈将,警方通過查閱死者的電腦和手機梢夯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晴圾,“玉大人颂砸,你說我怎么就攤上這事。” “怎么了人乓?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵勤篮,是天一觀的道長。 經(jīng)常有香客問我色罚,道長碰缔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任戳护,我火速辦了婚禮金抡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腌且。我一直安慰自己竟终,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布切蟋。 她就那樣靜靜地躺著,像睡著了一般榆芦。 火紅的嫁衣襯著肌膚如雪柄粹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天匆绣,我揣著相機與錄音驻右,去河邊找鬼。 笑死崎淳,一個胖子當(dāng)著我的面吹牛堪夭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拣凹,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼森爽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嚣镜?” 一聲冷哼從身側(cè)響起爬迟,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎菊匿,沒想到半個月后付呕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡跌捆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年徽职,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佩厚。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡姆钉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情育韩,我是刑警寧澤克蚂,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站筋讨,受9級特大地震影響埃叭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜悉罕,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一赤屋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧壁袄,春花似錦类早、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栈顷,卻和暖如春逆日,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萄凤。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工室抽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人靡努。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓坪圾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惑朦。 傳聞我的和親對象是個殘疾皇子兽泄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容