C++ 中的函数指针(Function Pointers)是指向函数的指针变量,它存储函数的地址,可以通过函数指针来调用函数。函数指针是 C++ 中实现回调函数、函数表和多态性的重要机制。

函数指针的基本概念

函数指针的声明和定义

#include <iostream>
 
// 普通函数
int add(int a, int b) {
    return a + b;
}
 
int subtract(int a, int b) {
    return a - b;
}
 
int main() {
    // 函数指针的声明语法:返回类型 (*指针名)(参数列表)
    int (*funcPtr)(int, int);
    
    // 将函数地址赋给函数指针
    funcPtr = add;        // 方式1:直接使用函数名
    funcPtr = &add;       // 方式2:使用取地址符(等价)
    
    // 通过函数指针调用函数
    int result1 = funcPtr(5, 3);     // 方式1:直接调用
    int result2 = (*funcPtr)(5, 3);  // 方式2:解引用调用(等价)
    
    std::cout << "Result1: " << result1 << std::endl;  // 8
    std::cout << "Result2: " << result2 << std::endl;  // 8
    
    // 改变函数指针指向的函数
    funcPtr = subtract;
    int result3 = funcPtr(5, 3);
    std::cout << "Result3: " << result3 << std::endl;  // 2
    
    return 0;
}

函数指针的初始化

// 声明时初始化
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }
 
int (*operation)(int, int) = multiply;  // 声明时初始化
 
// 数组初始化
int (*operations[])(int, int) = {add, subtract, multiply, divide};
 
// 使用函数指针数组
int main() {
    int x = 10, y = 5;
    
    for (int i = 0; i < 4; ++i) {
        int result = operations[i](x, y);
        std::cout << "Operation " << i << ": " << result << std::endl;
    }
    
    return 0;
}

函数指针的类型定义

使用 typedef 简化

// 复杂的函数指针声明
int (*complexFuncPtr)(int, double, char*);
 
// 使用 typedef 简化
typedef int (*BinaryOperation)(int, int);
typedef void (*EventHandler)(int eventType, void* data);
typedef double (*MathFunction)(double);
 
// 使用类型别名
BinaryOperation op = add;
EventHandler handler = nullptr;
MathFunction mathFunc = nullptr;
 
// 函数参数中使用
void processNumbers(int a, int b, BinaryOperation operation) {
    int result = operation(a, b);
    std::cout << "Result: " << result << std::endl;
}
 
int main() {
    processNumbers(10, 5, add);       // 传递 add 函数
    processNumbers(10, 5, subtract);  // 传递 subtract 函数
    
    return 0;
}

使用 using 声明(C++11)

// C++11 风格的类型别名
using BinaryOp = int(*)(int, int);
using Predicate = bool(*)(int);
using Callback = void(*)(const std::string&);
 
// 模板类型别名
template<typename T>
using Comparator = bool(*)(const T&, const T&);
 
// 使用示例
bool isEven(int n) { return n % 2 == 0; }
bool isPositive(int n) { return n > 0; }
 
void filterNumbers(const std::vector<int>& numbers, Predicate pred) {
    for (int num : numbers) {
        if (pred(num)) {
            std::cout << num << " ";
        }
    }
    std::cout << std::endl;
}
 
int main() {
    std::vector<int> numbers = {-2, -1, 0, 1, 2, 3, 4, 5};
    
    filterNumbers(numbers, isEven);     // 过滤偶数
    filterNumbers(numbers, isPositive); // 过滤正数
    
    return 0;
}

函数指针作为参数

回调函数

#include <vector>
#include <algorithm>
 
// 回调函数类型
typedef void (*ProgressCallback)(int percentage);
 
// 模拟长时间运行的任务
void longRunningTask(ProgressCallback callback = nullptr) {
    for (int i = 0; i <= 100; i += 10) {
        // 模拟工作
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        
        // 调用回调函数报告进度
        if (callback) {
            callback(i);
        }
    }
}
 
// 具体的回调函数实现
void printProgress(int percentage) {
    std::cout << "Progress: " << percentage << "%" << std::endl;
}
 
void updateProgressBar(int percentage) {
    std::cout << "[";
    int bars = percentage / 5;
    for (int i = 0; i < 20; ++i) {
        if (i < bars) std::cout << "=";
        else std::cout << " ";
    }
    std::cout << "] " << percentage << "%" << std::endl;
}
 
int main() {
    std::cout << "Task 1 with simple progress:" << std::endl;
    longRunningTask(printProgress);
    
    std::cout << "\nTask 2 with progress bar:" << std::endl;
    longRunningTask(updateProgressBar);
    
    std::cout << "\nTask 3 without callback:" << std::endl;
    longRunningTask();  // 不提供回调
    
    return 0;
}

策略模式实现

// 排序策略
bool ascending(int a, int b) { return a < b; }
bool descending(int a, int b) { return a > b; }
bool byAbsoluteValue(int a, int b) { return std::abs(a) < std::abs(b); }
 
// 排序函数,接受比较策略
void customSort(std::vector<int>& vec, bool (*comparator)(int, int)) {
    std::sort(vec.begin(), vec.end(), comparator);
}
 
// 搜索策略
typedef bool (*SearchPredicate)(int);
 
bool isEven(int n) { return n % 2 == 0; }
bool isOdd(int n) { return n % 2 != 0; }
bool isGreaterThan10(int n) { return n > 10; }
 
int findFirst(const std::vector<int>& vec, SearchPredicate predicate) {
    for (size_t i = 0; i < vec.size(); ++i) {
        if (predicate(vec[i])) {
            return i;
        }
    }
    return -1;  // 未找到
}
 
int main() {
    std::vector<int> numbers = {-5, 3, -12, 8, 15, -2, 7};
    
    // 不同的排序策略
    std::vector<int> temp = numbers;
    customSort(temp, ascending);
    std::cout << "Ascending: ";
    for (int n : temp) std::cout << n << " ";
    std::cout << std::endl;
    
    temp = numbers;
    customSort(temp, descending);
    std::cout << "Descending: ";
    for (int n : temp) std::cout << n << " ";
    std::cout << std::endl;
    
    temp = numbers;
    customSort(temp, byAbsoluteValue);
    std::cout << "By absolute value: ";
    for (int n : temp) std::cout << n << " ";
    std::cout << std::endl;
    
    // 不同的搜索策略
    int index = findFirst(numbers, isEven);
    std::cout << "First even number at index: " << index << std::endl;
    
    index = findFirst(numbers, isGreaterThan10);
    std::cout << "First number > 10 at index: " << index << std::endl;
    
    return 0;
}

函数指针作为返回值

返回函数指针

// 数学运算函数
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; }
 
// 返回函数指针的函数
typedef int (*Operation)(int, int);
 
Operation getOperation(char op) {
    switch (op) {
        case '+': return add;
        case '-': return subtract;
        case '*': return multiply;
        case '/': return divide;
        default:  return nullptr;
    }
}
 
// 更复杂的例子:函数工厂
typedef double (*MathFunction)(double);
 
double square(double x) { return x * x; }
double cube(double x) { return x * x * x; }
double squareRoot(double x) { return std::sqrt(x); }
 
MathFunction createMathFunction(const std::string& type) {
    if (type == "square") return square;
    if (type == "cube") return cube;
    if (type == "sqrt") return squareRoot;
    return nullptr;
}
 
int main() {
    // 使用运算符获取对应函数
    Operation op = getOperation('+');
    if (op) {
        std::cout << "10 + 5 = " << op(10, 5) << std::endl;
    }
    
    op = getOperation('*');
    if (op) {
        std::cout << "10 * 5 = " << op(10, 5) << std::endl;
    }
    
    // 使用数学函数工厂
    MathFunction func = createMathFunction("square");
    if (func) {
        std::cout << "square(5) = " << func(5) << std::endl;
    }
    
    func = createMathFunction("sqrt");
    if (func) {
        std::cout << "sqrt(25) = " << func(25) << std::endl;
    }
    
    return 0;
}

成员函数指针

普通成员函数指针

class Calculator {
public:
    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; }
    
    void printResult(int result) {
        std::cout << "Result: " << result << std::endl;
    }
};
 
int main() {
    // 成员函数指针的声明语法:返回类型 (类名::*指针名)(参数列表)
    int (Calculator::*operation)(int, int);
    void (Calculator::*printer)(int);
    
    // 赋值
    operation = &Calculator::add;  // 必须使用取地址符
    printer = &Calculator::printResult;
    
    // 调用成员函数指针
    Calculator calc;
    int result = (calc.*operation)(10, 5);  // 通过对象调用
    (calc.*printer)(result);
    
    // 通过指针调用
    Calculator* calcPtr = &calc;
    result = (calcPtr->*operation)(20, 8);
    (calcPtr->*printer)(result);
    
    // 改变指向的成员函数
    operation = &Calculator::multiply;
    result = (calc.*operation)(6, 7);
    (calc.*printer)(result);
    
    return 0;
}

成员函数指针的类型定义

class DataProcessor {
public:
    void processInt(int value) {
        std::cout << "Processing int: " << value << std::endl;
    }
    
    void processDouble(double value) {
        std::cout << "Processing double: " << value << std::endl;
    }
    
    void processString(const std::string& value) {
        std::cout << "Processing string: " << value << std::endl;
    }
};
 
// 成员函数指针的类型定义
typedef void (DataProcessor::*IntProcessor)(int);
typedef void (DataProcessor::*DoubleProcessor)(double);
typedef void (DataProcessor::*StringProcessor)(const std::string&);
 
// 使用 using 声明(C++11)
using IntHandler = void (DataProcessor::*)(int);
using DoubleHandler = void (DataProcessor::*)(double);
 
// 成员函数指针数组
void (DataProcessor::*processors[])(int) = {
    &DataProcessor::processInt
};
 
int main() {
    DataProcessor processor;
    
    IntProcessor intProc = &DataProcessor::processInt;
    DoubleProcessor doubleProc = &DataProcessor::processDouble;
    StringProcessor stringProc = &DataProcessor::processString;
    
    (processor.*intProc)(42);
    (processor.*doubleProc)(3.14);
    (processor.*stringProc)("Hello");
    
    return 0;
}

函数指针与多态

虚函数表的模拟

class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;
    virtual double perimeter() const = 0;
    virtual void draw() const = 0;
};
 
class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() const override {
        return 3.14159 * radius * radius;
    }
    
    double perimeter() const override {
        return 2 * 3.14159 * radius;
    }
    
    void draw() const override {
        std::cout << "Drawing circle with radius " << radius << std::endl;
    }
};
 
class Rectangle : public Shape {
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    
    double area() const override {
        return width * height;
    }
    
    double perimeter() const override {
        return 2 * (width + height);
    }
    
    void draw() const override {
        std::cout << "Drawing rectangle " << width << "x" << height << std::endl;
    }
};
 
// 使用函数指针实现多态行为
typedef double (Shape::*AreaCalculator)() const;
typedef void (Shape::*Drawer)() const;
 
void processShapes(const std::vector<std::unique_ptr<Shape>>& shapes) {
    AreaCalculator calcArea = &Shape::area;
    Drawer draw = &Shape::draw;
    
    for (const auto& shape : shapes) {
        (shape.get()->*draw)();
        double area = (shape.get()->*calcArea)();
        std::cout << "Area: " << area << std::endl << std::endl;
    }
}