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