首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C++ 函式指標與回呼函式實戰指南

     編輯:更多程式設計知識

核心概念速覽

  • 函式指標:指向可執行程式碼位址的指標,型別包含回傳值與參數列表。
  • 回呼函式:透過函式指標傳遞給另一個函式,由被呼叫者在適當時機調用的函式。

一、函式指標宣告語法

// 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、呼叫慣例、成員函式指標語法即可游刃有餘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved