深度探索C++對象模型-第四章

說明:

? <u>不是很清楚的點</u>,用下劃線。

? 解答,用斜體;

? 重點,用粗體加粗;

第四章 Function 語意學(xué)

4.1 Member的各種調(diào)用方式

1. Nonstatic Member Functions

實際上編譯器是將member function被內(nèi)化為nonmember的形式,經(jīng)過下面轉(zhuǎn)化步驟:

  1. 給函數(shù)添加額外參數(shù)——this;
  2. 將對每一個nonstaitc data member的存取操作改為this指針來存取;
  3. 將member function 重寫成一個外部函數(shù)。對函數(shù)名采用mangling 處理,使之成為獨一無二的語匯;

2. Virtual Member Functions(虛成員函數(shù))

? ptr->f(); //f()為虛成員函數(shù)

內(nèi)部轉(zhuǎn)化為

? (*ptr->vptr[1])(ptr);

其中:

  • vptr表示編譯器產(chǎn)生的指針,指向virtual table。它被安插在每一個聲明有(或繼承自)一個或多個virtual functions 的class object 中。
  • 1 是virtual table slot的索引值,關(guān)聯(lián)到normalize()函數(shù)。
  • 第二個ptr表示this指針。

3. Static Member Functions (靜態(tài)成員函數(shù))

Static Member Functions的主要特性就是它沒有this指針

次要特性:

  • 不能被聲明為const、volatile、virtual;
  • 不能夠直接存取其class中的非靜態(tài)數(shù)據(jù)成員;

Static Member Functions由于缺乏this指針,因此差不多等同于非成員函數(shù)。

如果取一個static member function 的地址,獲得的是其在內(nèi)存的位置(也就是地址),而不是一個指向“class member function”的指針,如下:

&Point::count();

會得到一個數(shù)值,類型是:

unsigned int(*)();

而不是:

unsigned int(Point::*)();

4.2 Virtual Member Functions

C++中,多態(tài)表示以“一個public base class 的指針(或reference),尋址出一個derived class object”。

為了在執(zhí)行期調(diào)用正確的虛函數(shù),在編譯時期:

  • 可以在每一個多態(tài)的class object身上增加兩個members:
  1. 一個字符串或數(shù)字,表示class的類型;
  2. 一個指針vptr,指向某一個表格,表格中持有程序的虛函數(shù)們的執(zhí)行期地址;
  • 每一個虛函數(shù)都被指派一個表格索引值;

那么,表格中的虛函數(shù)們地址如何被購建起來?

在C++中,虛函數(shù)們可經(jīng)由其class object被調(diào)用,可以在編譯時期獲知。此外,這一組地址是固定不變的,執(zhí)行期不可能新增或替換之。由于程序執(zhí)行時,表格的大小和內(nèi)容都不會改變,所以其建構(gòu)和存取皆可以由編譯器完全掌控。不需要執(zhí)行期的任何介入。**

執(zhí)行期要做的,只是在特定的虛函數(shù)表slot中激活虛函數(shù)。


每一個class 只會有一個virtual table,每一個table 含有對應(yīng)的class object中所有active virtual functions 函數(shù)實體地址。這些active virtual function 包括:

  1. 這個class 所定義的函數(shù)實體(包括改寫一個可能存在的base class virtual function函數(shù)實體)。
  2. 繼承自base class 的函數(shù)實體(不被derived class改寫)
  3. 一個pure_virtual_called()。

繼承過程中,virtual table的三種可能性:

  1. 繼承base class 所聲明的virtual functions的函數(shù)實體。正確地說,是該函數(shù)實體的地址會被拷貝到derived class的virtual table相對應(yīng)的slot之中。
  2. 使用自己的函數(shù)實體。這表示它自己的函數(shù)實體地址必須放在對應(yīng)的slot之中。
  3. 可以加入一個新的virtual function。這時候virtual table 的尺寸會增大一個slot放進這個函數(shù)實體地址。

編譯時期設(shè)定virtual function的調(diào)用:

ptr->z();

  • 一般而言,我并不知道ptr 所指對象的真正類型。然而可以經(jīng)由ptr 可以存取到該對象的virtual table。
  • 雖然我不知道哪個Z()函數(shù)實體被調(diào)用,但知道每一個Z()函數(shù)地址都被放置某一個slot(如slot 4)的索引。

這樣我們就可以將

ptr->z();

轉(zhuǎn)化為:

(*ptr->vptr[4])(ptr);

唯一一個在執(zhí)行期才能知道的東西是:slot4所指的到底是哪一個class object的z()函數(shù)實體。

多重繼承下的 Virtual Functions

在多重繼承中支持virtual functions,其復(fù)雜度圍繞在第二個及其后面的base class 上,以及“必須在執(zhí)行期調(diào)整this 指針”這一點。

一般規(guī)則是,經(jīng)由指向“第二或后繼base class 的指針”來調(diào)用derived class virtual function。調(diào)用操作連帶的“必要的this指針調(diào)整”操作,必須在執(zhí)行期完成。

在多重繼承下,一個派生類內(nèi)含n-1個額外的虛函數(shù)表,n表示其上一層基類的個數(shù)(因此,單一繼承將不會有額外的虛函數(shù)表)?!救羰请p重繼承,那么就會有一個與派生類共享的虛函數(shù)表

如下圖:

4-2.png

【注】

  • base1的虛函數(shù)表是主要表格,base2的是次要表格;
  • 函數(shù)后面有加*,表示這不是真實的函數(shù)實例,是需要加this指針指向真正的函數(shù)實例。

4.3 函數(shù)的效能

non-member、static member或non-static member函數(shù)都被轉(zhuǎn)換為完全相同形式,所以三者效率完全相同。

4.4 指向Member Function的指針

取一個non-static data member的地址,得到的結(jié)果是該member在class 布局中的bytes位置(再加1),所以它需要綁定于某個class object的地址上,才能夠被存取。

取一個non-static member function的地址,如果該函數(shù)是non-virtual,則得到的是內(nèi)存的真正地址,然后這個值也是不完全的,也需要綁定于某個class object的地址上,才能夠調(diào)用函數(shù)。(所有的non-static member function都需要對象的地址,以參數(shù)this指出)

支持“指向Virtual Member Function”之指針

對于一個virtual function,其地址在編譯時期是未知的,所能知道的僅是virtual function在其相關(guān)之virtual table的索引值,也就是說,對于一個virtual member function 取其地址,所能獲得的只是一個索引值。

4.5 Inline Function

形參:

  • 傳入?yún)?shù),直接替換;
  • 傳入常量,連替換都省了,直接變成常量;
  • 傳入函數(shù)運行結(jié)果,則需要導(dǎo)入臨時變量,以避免重復(fù)求值;

局部變量:

一般而言,inline函數(shù)中的每一個局部變量都必須被放在函數(shù)調(diào)用的一個封閉區(qū)段中,擁有一個獨一無二的名稱。

如果一次性調(diào)用N次,就會出現(xiàn)N個臨時變量……程序的體積會暴增,如下:

minval = min( val1, val2 ) + min( foo(), foo()+1 );

因此要以分離的多個式子被調(diào)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容