C++類成員函數指針使用介紹

前言

在之前寫過的博客中有介紹過函數指針和指針函數的區別和簡單用法(文章在這裏),當時的Demo非常簡單,都是C語言的寫法,但是當在C++中直接像C那樣使用類成員函數指針時就會報錯:reference to non-static member function must be called
所以如果是C++中的成員函數指針其使用方法是有區別的,這裏針對不同的場景做個補充說明。

類成員函數的指針(非靜態)

指向類成員函數的指針與普通函數指針的區別在於,前者需要匹配函數的參數類型和個數以及返回值類型,還要匹配該函數指針所屬的類類型。

這是因爲非靜態的成員函數必須被綁定到一個類的對象或者指針上,才能得到被調用對象的this指針,然後才能調用指針所指的成員函數(所有類的對象都有自己數據成員的拷貝,但是成員函數都是共用的,爲了區分是誰調用了成員函數,就必須有this指針,this指針是隱式的添加到函數參數列表裏去的)。

所以,對於類成員函數的指針使用包含以下幾個步驟:

聲明: 指向類的成員函數的指針需要在指針前面加上類的類型,格式爲:

typedef 返回值 (類名::*指針類型名)(參數列表);

賦值: 需要用類的成員函數地址賦值,格式爲:

指針類型名  指針名 = &類名::成員函數名;

注意:這裏的這個&符號是比較重要的:不加&,編譯器會認爲是在這裏調用成員函數,所以需要給出參數列表,否則會報錯;加了&,才認爲是要獲取函數指針。這是C++專門做了區別對待。

調用: 針對調用的對象是對象還是指針,分別用.*和->*進行調用,格式爲:

(類對象.*指針名)(參數列表);

(類指針->*指針名)(參數列表);

注意:這裏的前面一對括號是很重要的,因爲()的優先級高於成員操作符指針的優先級。

直接來看一個示例吧:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章