// 1. 直接宣告變數
void (*pf)(int, int);
// 2. 使用 typedef 簡化(推薦)
typedef void (*FunPtr)(int, int);
FunPtr pf;
// 3. C++11 using 別名(更清晰)
using FunPtr = void(*)(int, int);
#include <iostream>
using namespace std;
void minVal(int a, int b) { cout << "min = " << (a<b?a:b) << '\n'; }
void maxVal(int a, int b) { cout << "max = " << (a>b?a:b) << '\n'; }
int main() {
using FunPtr = void(*)(int, int);
FunPtr pf = nullptr;
pf = &minVal; // 取址符可省略
pf(3, 5); // 輸出 min = 3
pf = maxVal;
pf(3, 5); // 輸出 max = 5
// 陣列形式管理多個回呼
FunPtr callbacks[] = {minVal, maxVal};
for (auto f : callbacks) f(10, 20);
}
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
// 回呼型別:接收元素,回傳 bool 表示是否保留
using FilterFunc = bool(*)(int);
vector filter(const vector& src, FilterFunc pred) {
vector dst;
for (int v : src) if (pred(v)) dst.push_back(v);
return dst;
}
bool isEven(int x) { return x % 2 == 0; }
bool isPositive(int x) { return x > 0; }
int main() {
vector data = {-3, -2, -1, 0, 1, 2, 3, 4, 5};
auto evens = filter(data, isEven);
auto pos = filter(data, isPositive);
cout << "Even: "; for (int v: evens) cout << v << ' '; cout << '\n';
cout << "Pos: "; for (int v: pos) cout << v << ' '; cout << '\n';
}
std::function 與 Lambda(C++11)現代 C++ 建議改用 std::function 支援 Lambda、仿函式、綁定器:
#include <functional>
#include <iostream>
using namespace std;
void execute(function callback, int a, int b) {
callback(a, b);
}
int main() {
// Lambda 直接傳遞
execute([](int x, int y){ cout << "Sum: " << x+y << '\n'; }, 3, 4);
// 綁定成員函式
struct Adder { void add(int a, int b) { cout << a+b << '\n'; } } obj;
execute(bind(&Adder::add, &obj, placeholders::_1, placeholders::_2), 5, 6);
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 指標型別不匹配 | 參數順序、const、引用差異導致簽章不同 | 統一使用 typedef/using 定義型別別名 |
| 呼叫慣例不一致 | Windows API 使用 __stdcall,預設為 __cdecl | 明確指定 void (__stdcall *pf)(int) |
| 成員函式指標語法複雜 | 需物件實例配合 .* / ->* 呼叫 | 改用 std::function + std::bind 或 Lambda 捕獲 this |
| 回呼生命週期管理 | Lambda 捕獲參考導致懸空指標 | 以值捕獲 [=] 或共享擁有權 shared_ptr |
函式指標是 C 風格回呼基石,C++11 後 std::function、Lambda、auto 大幅降低複雜度。新專案優先採用現代寫法;維護舊代碼時,熟悉 typedef、呼叫慣例、成員函式指標語法即可游刃有餘。