開始整理第四章的内容,關于函數的東西。
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::*)()(關于指向類成員函數的指針,跟指向類成員變量的指針有點類似,之後會有整理)。