S SmartDocs
Serie: C++ cpp 172 righe · Aggiornato 2026-06-15

function_pointers.cpp

C++/Part1_基礎入門/Ch06_指標與參考/function_pointers.cpp

// ============================================================
// Ch06 — 函式指標(Function Pointers)
// 編譯:g++ -std=c++17 -Wall -o function_pointers function_pointers.cpp
// ============================================================

#include <iostream>
#include <functional>
#include <string>
#include <vector>

// ── 基本算術函式 ──
int add(int a, int b)       { return a + b; }
int subtract(int a, int b)  { return a - b; }
int multiply(int a, int b)  { return a * b; }
int divide(int a, int b)    { return (b != 0) ? a / b : 0; }

// ── 函式原型 ──
void demonstrateBasicFunctionPointer();
void demonstrateFunctionPointerArray();
void demonstrateCallback();
void demonstrateReturnFunctionPointer();
int applyOperation(int a, int b, int (*op)(int, int));
void forEach(int* arr, int size, void (*action)(int&));
void printElement(int& val);
int calculate(int* arr, int size, const std::function<int(int, int)>& op);
void demonstrateStdFunction();
void demonstrateLambdaAsFunctionPointer();

// ── 主程式 ────────────────────────────────────────
int main() {
    std::cout << "===== Ch06:函式指標 =====\n\n";

    demonstrateBasicFunctionPointer();
    demonstrateFunctionPointerArray();
    demonstrateCallback();
    demonstrateReturnFunctionPointer();
    demonstrateStdFunction();
    demonstrateLambdaAsFunctionPointer();

    return 0;
}

// ── 1. 函式指標基礎 ──
void demonstrateBasicFunctionPointer() {
    std::cout << "【1】函式指標基礎\n";

    // 宣告:回傳型別 (*指標名)(參數型別列表)
    int (*funcPtr)(int, int) = nullptr;

    funcPtr = add;           // 函式名會自動轉為函式位址
    std::cout << "funcPtr = add\n";
    std::cout << "funcPtr(3, 5)   = " << funcPtr(3, 5) << "\n";
    std::cout << "(*funcPtr)(3, 5) = " << (*funcPtr)(3, 5) << "(等價寫法)\n";

    funcPtr = multiply;
    std::cout << "funcPtr = multiply → funcPtr(4, 6) = " << funcPtr(4, 6) << "\n\n";
}

// ── 2. 函式指標陣列(策略模式雛形) ──
void demonstrateFunctionPointerArray() {
    std::cout << "【2】函式指標陣列\n";

    int (*operations[])(int, int) = {add, subtract, multiply, divide};
    const char* names[] = {"加", "減", "乘", "除"};

    int x = 20, y = 4;
    for (int i = 0; i < 4; i++) {
        std::cout << x << " " << names[i] << " " << y
                  << " = " << operations[i](x, y) << "\n";
    }
    std::cout << "\n";
}

// ── 3. 函式指標作為 callback ──
int applyOperation(int a, int b, int (*op)(int, int)) {
    return op(a, b);
}

void forEach(int* arr, int size, void (*action)(int&)) {
    for (int i = 0; i < size; i++) {
        action(arr[i]);
    }
}

void printElement(int& val) {
    std::cout << val << " ";
}

void demonstrateCallback() {
    std::cout << "【3】函式指標作為 Callback\n";

    std::cout << "applyOperation(10, 3, add)      = "
              << applyOperation(10, 3, add) << "\n";
    std::cout << "applyOperation(10, 3, subtract)   = "
              << applyOperation(10, 3, subtract) << "\n";

    int data[] = {1, 2, 3, 4, 5};
    std::cout << "forEach 印出:";
    forEach(data, 5, printElement);
    std::cout << "\n\n";
}

// ── 4. 回傳函式指標 ──
int (*selectOperation(char op))(int, int) {
    switch (op) {
        case '+': return add;
        case '-': return subtract;
        case '*': return multiply;
        case '/': return divide;
        default:  return add;
    }
}

void demonstrateReturnFunctionPointer() {
    std::cout << "【4】回傳函式指標\n";

    char ops[] = {'+', '-', '*', '/'};
    int a = 12, b = 3;

    for (char op : ops) {
        int (*selected)(int, int) = selectOperation(op);
        std::cout << a << " " << op << " " << b
                  << " = " << selected(a, b) << "\n";
    }
    std::cout << "\n";
}

// ── 5. std::function(現代 C++ 替代方案) ──
int calculate(int* arr, int size, const std::function<int(int, int)>& op) {
    int result = arr[0];
    for (int i = 1; i < size; i++) {
        result = op(result, arr[i]);
    }
    return result;
}

void demonstrateStdFunction() {
    std::cout << "【5】std::function(現代替代方案)\n";

    int arr[] = {2, 3, 4, 5};

    std::cout << "累加 arr = " << calculate(arr, 4, add) << "\n";
    std::cout << "累乘 arr = " << calculate(arr, 4, multiply) << "\n";

    // 可接受 capturing lambda(函式指標做不到)
    int offset = 10;
    auto withOffset = [offset](int a, int b) { return a + b + offset; };
    std::cout << "帶 offset 的累加 = " << calculate(arr, 4, withOffset) << "\n\n";
}

// ── 6. Lambda 與函式指標的關係 ──
void demonstrateLambdaAsFunctionPointer() {
    std::cout << "【6】Lambda 與函式指標\n";

    // 無 capture 的 lambda 可轉為函式指標
    int (*lambdaPtr)(int, int) = [](int a, int b) { return a * a + b * b; };
    std::cout << "lambdaPtr(3, 4) = " << lambdaPtr(3, 4) << "(3² + 4²)\n";

    // 有 capture 的 lambda 不能轉為函式指標,需用 std::function
    int factor = 2;
    // int (*bad)(int, int) = [factor](int a, int b) { return (a + b) * factor; }; // 編譯錯誤
    std::function<int(int, int)> good = [factor](int a, int b) {
        return (a + b) * factor;
    };
    std::cout << "std::function + capturing lambda: good(3, 4) = "
              << good(3, 4) << "\n\n";

    std::cout << "【7】選擇建議\n";
    std::cout << "  函式指標     → C 互操作、零 overhead、效能關鍵路徑\n";
    std::cout << "  std::function → 需要儲存 callback、接受 lambda / functor\n";
    std::cout << "  template     → 編譯期多型,最佳效能(進階主題)\n";
}

Articoli correlati