天天看點

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測試通過,有問題歡迎交流。

繼續閱讀