之前一直以爲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測試通過,有問題歡迎交流。