《深度探索C++對象模型》讀書筆記之Function語意學

C++支持三種類型的成員函數:staticnonstaticvirtual

 

1C++的設計準則中說:非靜態成員函數至少必須和一般的非成員函數有相同的效率。這是如何做到的?

C++中的member function實際上被轉化爲nonmember的形式。下面是轉化的步驟:

1>    改寫函數的原型,安插一個額外的參數(this指針)到member function中,使得class object得以調用該函數。

Point3d Point3d::magnitude()

Point3d Point3d::magnitude() const

       分別被轉化爲

Point3d Point3d::magnitude(Point*const this)

Point3d Point3d::magnitude(const Point*const this)

2>    將每個“隊nonstatic data member的存取操作”改爲經由this指針來存取

3>    member function重寫成一個外部函數,對名稱進行“mangling”處理,使它在程序中成爲獨一無二的詞彙。(name mangling的方法請Google之)

備註:靜態函數的轉化不難想象。而實際正如想象的那樣。

 

2static memberfunction有何不同?

         靜態成員函數的主要特性是它沒有this指針,以下次要特性統統根源於其主要特性:

1>    不能夠直接存取其class中的nonstatic members

2>    不能夠被聲明爲constvolatilevirtual(前兩者是爲了限制nonstatic member,既然不能存取nonstatic members當然也不能使用這兩者咯,後者虛機制,你懂的~

3>    不需要經由class object才被調用

 

3virutal memberfunction如何被調用?你會如果利用這些特性去優化你的程序?

1>    指針或者引用調用,會轉變成通過虛函數指針調用虛函數表中的該函數(有一個決議的過程,低效啊!!!)

//register float mag = magnitude();

register float mag = (*this ->vptr[2])(this);

2>    如果能確定調用函數使用實體調用虛函數可以壓抑由於虛機制而產生的不必要的重複操作。

//明確的調用會壓抑虛機制

register float mag =Point3d::magnitude();

上述等同於調用一個nonstatic member function

 

4、虛函數的決議的支持機制是怎樣的?

   1、單一繼承:  

     編譯期:

1>    爲每個有虛函數的類配一張虛函數表,它存儲該類類型信息和所有虛函數執行期的地址。

2>    爲每個有虛函數的類插入一個指針(vptr,這個指針指向該類的虛函數表。

3>    給每一個虛函數指派一個在表中的索引。

執行期:在特定的virtual tableslot中激活virtual function。雖然我們並不知道ptr所指對象的真正類型,然而,經由ptr可以存取到該對象的virtual table。雖然我們不知道哪個f()將被調用,但我們知道每一個f()函數的地址都被放在第nslot

備註:構建virtualtable有三種情況:一、繼承自base class的函數實體,其實體地址拷貝到對應的slot;二、類定義的函數體使用自己的函數實體地址放在對應的slot;三、類新加入的函數,增加virtual table尺寸,將新函數實體地址放入該slot。(純虛函數可以起到佔位作用,也要添加到virtual table中)

2、多重繼承:

在多重繼承中支持virtualfunction,其複雜度圍繞在第二個及後繼的base classes身上,必須在執行期調整this指針。解決的方式大致有一、Bjame的解決方法;二、thunk的方法。(在此不作多說,詳細可參閱書籍)

3、虛繼承:

         略(因爲太過複雜,書籍上並未詳細講解)。

 

5inline函數背後做了什麼?

形式參數:每個形式參數都會被對應的實際參數取代;如果實際參數是個常量表達式則以臨時變量代換之,避免重複求值。

局部變量:如果inline函數以單一的表達式擴展多次,那麼每次擴展都需要自己的一組局部變量。如果inline函數以分離的多個式子被擴展多次,那麼只需要一組局部變量。

   備註:由於參數的副作用(使用太多啓代換作用的臨時變量),以單一表達式做多重調用,或是在inline函數中有多個局部變量,都會產生臨時性對象。產生的大量的擴展碼,使程序的大小暴漲。

發佈了147 篇原創文章 · 獲贊 25 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章