第四章:指向成員函式的指標
阿新 • • 發佈:2021-06-24
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。