天天看點

[讀書筆記] 深入探索C++對象模型-第四章-Function語義學(上)

開始整理第四章的内容,關于函數的東西。

1. 靜态成員函數不可以是const的,原因是因為this指針,詳細參考:http://blog.csdn.net/beyongwang/article/details/52403697

2. 成員函數可以分成幾類:

a. 非靜态成員函數:此類函數會隐含一個this指針傳入函數體,舉個例子,對于如下函數:

float A::non_Static_Fun(){
    return m_a * m_a;
}
           

調用步驟如下:改寫函數簽名,添加this指針,對于const函數,會添加const A* this:

float A::non_Static_Fun(A* this){
    ...
}
           

将每一個非靜态資料成員的存取改為由this指針來做:

float A::non_Static_Fun(A* this){
    return this->m_a * this->m_a;
}
           

将成員函數重新寫成一個外部函數,對函數名字進行mangling處理,一般的處理方法是函數名稱+參數數目+加參數類型,注意沒有傳回值,這也是為什麼C++中,函數重載不允許通過傳回值來區分,(添加extern C關鍵字可以阻止這種mangling),使其成為獨一無二函數名字:

extern non_Static_Fun_7AFv(...);
           

相應的對于這個函數的調用操作也會被轉換:

a.non_Static_Fun();
           

會轉化為

non_Static_Fun_7AFv(&a);
           

指針調用:

pa->non_Static_Fun();
           

會轉化成:

non_Static_Fun_7AFv(pa);
           

b. 虛拟成員函數:嚴格來說,虛函數也屬于非靜态成員函數,二者擁有部分相同的處理,但是由于跟普通的非靜态成員函數處理上又有所不同,是以單獨分成一類。例如,如果對于類A的一個虛成員函數v_Fun(void),這個調用pa->v_Fun(),可能會被轉成為(* pa->vptr[1])(pa);其中,

    i. vptr是編譯器産生的指向虛表的指針,對于所有含有或者繼承有虛函數的類,都會存在,其名字可能也會被mangling化,因為同一個類中可能存在        多個此類指針。

    ii. 1是虛表槽的索引值,說明此函數位于虛表第二個函數槽中。

    iii. 第二個pa表示this指針。

注意,使用類對象調用虛函數和調用非虛函數的處理是一樣的,并不會涉及虛表,例如:a.v_Fun()會轉化為:v_Fun_7AFv(&a),跟上面調用非靜态成員函數是一樣的。這是因為類對象的類型是确定的,是以不必通過虛函數機制來決定被調用函數的位址。

c. 靜态成員函數:

靜态成員函數跟非靜态成員函數的差別在于,前者沒有this指針,因為從所屬關系上來看,前者屬于整個類,不存儲特定的類執行個體狀态,而後者可能因為不同的執行個體而産生不同的結果。例如,對于類A的一個靜态成員函數void static_Fun(void),這個調用pa->static_Fun();以及這個調用:a.static_Fun();都會轉化為一般的非成員函數調用:static_Fun_7ASFv();

幾個靜态函數的特征:

    i. 它不能直接存取所屬類的非靜态資料成員。

    ii. 它不能被聲明為const, volatile或者virtual。

    iii. 它不需要通過類執行個體對象調用,A::static_Fun()。

取靜态成員函數的位址: &A::static_Fun(),得到的是其在記憶體中的位置,也就是一個普通的函數指針:void (*)(),而不是指向類成員函數的指針void (A::*)()(關于指向類成員函數的指針,跟指向類成員變量的指針有點類似,之後會有整理)。

繼續閱讀