前言
在以前寫過的博客中有介紹過函數指針和指針函數的區別和簡單用法(文章在這裏),當時的Demo很是簡單,都是C語言的寫法,可是當在C++中直接像C那樣使用類成員函數指針時就會報錯:reference to non-static member function must be called
因此若是是C++中的成員函數指針其使用方法是有區別的,這裏針對不一樣的場景作個補充說明。html
類成員函數的指針(非靜態)
指向類成員函數的指針與普通函數指針的區別在於,前者須要匹配函數的參數類型和個數以及返回值類型,還要匹配該函數指針所屬的類類型。函數
這是由於非靜態的成員函數必須被綁定到一個類的對象或者指針上,才能獲得被調用對象的this指針,而後才能調用指針所指的成員函數(全部類的對象都有本身數據成員的拷貝,可是成員函數都是共用的,爲了區分是誰調用了成員函數,就必須有this指針,this指針是隱式的添加到函數參數列表裏去的)。this
因此,對於類成員函數的指針使用包含如下幾個步驟:.net
聲明: 指向類的成員函數的指針須要在指針前面加上類的類型,格式爲:指針
typedef 返回值 (類名::*指針類型名)(參數列表);
賦值: 須要用類的成員函數地址賦值,格式爲:htm
指針類型名 指針名 = &類名::成員函數名;
1
注意:這裏的這個&符號是比較重要的:不加&,編譯器會認爲是在這裏調用成員函數,因此須要給出參數列表,不然會報錯;加了&,才認爲是要獲取函數指針。這是C++專門作了區別對待。對象
調用: 針對調用的對象是對象仍是指針,分別用.*和->*進行調用,格式爲:blog
(類對象.*指針名)(參數列表);編譯器
(類指針->*指針名)(參數列表);
注意:這裏的前面一對括號是很重要的,由於()的優先級高於成員操做符指針的優先級。博客
直接來看一個示例吧:
class Calculation
{
public:
int add(int a,int b){ //非靜態函數
return a + b;
}
};
typedef int (Calculation::*FuncCal)(int,int);
int main()
{
FuncCal funAdd = &Calculation::add;
Calculation * calPtr = new Calculation;
int ret = (calPtr->*funAdd)(1,2); //經過指針調用
Calculation cal;
int ret2 = (cal.*funAdd)(3,4); //經過對象調用
cout << "ret = " << ret << endl;
cout << "ret2 = " << ret2 << endl;
return 0;
}
指向類的靜態函數的指針
類的靜態成員函數和普通函數的函數指針的區別在於,他們是不依賴於具體對象的,全部實例化的對象都共享同一個靜態成員,因此靜態成員也沒有this指針的概念。
因此,指向類的靜態成員的指針就是普通的指針。
class Calculation
{
public:
static int add(int a,int b){ //非靜態函數
return a + b;
}
};
typedef int (*FuncCal)(int,int);
int main()
{
FuncCal funAdd = &Calculation::add;
int ret = (*funAdd)(1,2); //直接引用
int ret2 = funAdd(3,4); //直接引用
cout << "ret = " << ret << endl;
cout << "ret2 = " << ret2 << endl;
return 0;
}
總結以上兩種狀況的區別:
若是是類的靜態成員函數,那麼使用函數指針和普通函數指針沒區別,使用方法同樣
若是是類的非靜態成員函數,那麼使用函數指針須要加一個類限制一下。
使用函數指針,不少狀況下是用在函數的參數中,在一些複雜的計算,若是須要重複調用,而且每次調用的函數不同,那麼這時候使用函數指針就很方便了,能夠減小代碼量。
參考資料: https://blog.csdn.net/houzijushi/article/details/81503409 https://www.cnblogs.com/lvchaoshun/p/7806248.html https://www.cnblogs.com/AnnieKim/archive/2011/12/04/2275589.html ————————————————