C/C++普通函數指針和類成員函數指針的使用

之前一直以爲C++成員函數沒法取地址,一直使用靜態函數來充當回調函數,直到近日看別人的代碼才發現類成員函數也有指針。。。總結記錄一下。

普通函數指針

這面是普通函數的指針的使用方法。

#include <stdio.h>

void printSum(int a, int b) {
    printf("%d + %d = %d\n", a, b, a+b);
}

int main() {
    // 聲明一個函數指針變量,和聲明一個普通變量類似,只是需要把這個變量名字放在這一串字符中間而已。
    void (*sum)(int, int); 

    sum = &printSum; // 帶不帶&符號都一樣效果,函數名也表示地址。
    // sum = printSum;  // 也可以這樣
    
    sum(1, 2);
    printf("%p %p \n", printSum, &printSum);  // 打印出來的地址是一樣的,所以上面加不加&符號效果都一樣
    printf("%p %p \n", sum, *sum);
    return 0;
}

輸出

1 + 2 = 3
0x10162ded0 0x10162ded0  // 輸出的四個地址都是一樣的
0x10162ded0 0x10162ded0 

關於 typedef 函數指針類型

可以對照普通用法看一看

// 直接聲明變量
int i = 1;
void (*sum)(int, int) = printSum;

// 使用typedef
typedef int INT;
INT a = 1;

typedef void (*SUM)(int, int);
SUM fun = printSum;

類成員函數指針

與普通成員函數指針相比,類成員函數指針必須加上類名::

#include <stdio.h>

class Sample {
public:
    void printSum(int a, int b){
        printf("%d + %d = %d\n", a, b, a+b);
    }
};

int main() {
    void (Sample::*sum)(int, int);

    sum = &Sample::printSum; // 這個必須加&,與普通函數不同

    Sample *ins = new Sample;

    (ins->*sum)(1, 2); // 注意:這裏需要加星*

    printf("%p", &Sample::printSum);

    return 0;
}

輸出

1 + 2 = 3
0x10300ef40

typedef 成員函數指針類型

typedef void (Sample::*SUM)(int, int);
SUM sum = &Sample::printSum;

總結

還是以上面的代碼函數的定義爲例:

  • 普通成員函數的類型爲void (*)(int, int),類成員函數類型爲void (Sample::*)(int, int),後者一定要加類名
  • 函數指針的定義和普通函數類似,區別是普通函數的變量名寫在類型後面,函數指針類型變量名寫在類型中間
  • 普通函數的函數名可以作爲函數入口指針,加不加&符號都一樣效果,類成員函數的指針必須加&符號,調用的時候也必須加*。 可以理解爲普通函數名字等同於地址,成員函數的名字和地址不是一個東西。

代碼在Mac gcc測試通過,有問題歡迎交流。

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