1. 程式人生 > 其它 >第四章:指向成員函式的指標

第四章:指向成員函式的指標

  1.指向作用域運算子(書裡叫成員選擇運算子)"::"的指標的作用是儲存this指標。所以靜態成員函式指標(沒有this)的型別是函式指標,而不是成員函式的指標。

  2.指向成員函式的指標有兩種功能:①呼叫普通的成員函式②呼叫虛成員函式

  對前者取地址得到的是該函式在記憶體中的真實地址,而後者取地址得到的是虛擬函式在虛擬函式表中的索引值。所以一個成員函式指標必須能分辨指向的是上述哪兩種地址,在cfront2.0中的解決辦法如下:

float (Point::*pmf)();
Point *ptr;
//判斷是哪種情況
(((int)pmf) &~127)       //pmf如果是索引且最大索引小於127則被置為0
? (*pmf)(ptr) // 非虛擬函式 : (*ptr->vptr[(int)pmf](ptr)); //虛擬函式

  上述判斷需要一定的開銷。

  3.多重繼承和虛擬繼承情況下的指向成員函式的指標

  (1)Stroustrup提出了以下結構來支援多重繼承和虛擬繼承的成員函式指標。

struct _mptr{
int delata //表示可能的this指標調整值
int index;  //虛擬函式表的索引值,-1表示非虛擬函式
union {
ptrtofunc faddr; //非虛擬函式的地址
int          v_offset; //放置第二個或後繼繼承鏈中虛基類的虛擬函式表的位置,如果vptr放在類物件的開頭處則不必要但是會降低對C結構的相容性
};};

  此模型下需要改正2中所提到的判斷。這個判斷會導致指向非虛擬函式的指標也增加判斷這一條件,並且當傳遞一個不變指標給成員函式時,他需要產生一個臨時物件(因為要配置上述這個結構體,普通情況下直接產生一個臨時指標即可)

(pmf.index<0)
?(*pmf.faddr)(ptr)    //非虛擬函式
:(*ptr->vptr[pmf.index](ptr)); //虛擬函式  

  (2)為了減少對指向非虛成員函式指標判斷所帶來的成本,Microsoft取消判斷,匯入一個vcall thunk。此策略下,faddr被指定要不就是真正的member function地址,要不就是vcall thunk地址。vcall thunk會選出並呼叫相關virtual table中的slot。