C++学习笔记-函数指针

函数指针是指向函数的指针变量,它可以存储函数的地址并通过指针调用函数。函数指针在回调函数、事件处理、策略模式等场景中非常有用。

函数指针的基本概念

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <vector>

/* 函数指针是一个变量,它可以存储函数的地址 */
void Callback(int value)
{
    std::cout << "Value: " << value << std::endl;
}

void ForEach(const std::vector<int>& values, void(*func)(int))
{
    for (int value : values)
        func(value);
}

int main()
{
    // 函数指针的声明和赋值
    void(*callback)(int) = Callback;  // void是返回值类型,callback是函数名,(int)是参数列表,这是C风格的函数指针
    
    // 也可以使用auto自动推导
    auto callback2 = Callback;
    
    std::vector<int> values = {1, 2, 3, 4, 5};
    ForEach(values, Callback);     // 直接传递函数名
    ForEach(values, callback);     // 传递函数指针
    ForEach(values, callback2);    // 传递auto推导的函数指针
    
    return 0;
}

不同类型的函数指针

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>

// 无参数函数
void SayHello()
{
    std::cout << "Hello, World!" << std::endl;
}

// 有返回值的函数
int Add(int a, int b)
{
    return a + b;
}

// 多参数函数
void PrintInfo(const std::string& name, int age, double salary)
{
    std::cout << "Name: " << name << ", Age: " << age << ", Salary: $" << salary << std::endl;
}

// 函数指针作为参数
int Calculate(int a, int b, int(*operation)(int, int))
{
    return operation(a, b);
}

int Multiply(int a, int b)
{
    return a * b;
}

int Subtract(int a, int b)
{
    return a - b;
}

int main()
{
    // 无参数函数指针
    void(*greetFunc)() = SayHello;
    greetFunc();
    
    // 有返回值的函数指针
    int(*addFunc)(int, int) = Add;
    int result = addFunc(10, 20);
    std::cout << "10 + 20 = " << result << std::endl;
    
    // 多参数函数指针
    void(*printFunc)(const std::string&, int, double) = PrintInfo;
    printFunc("Alice", 30, 75000.0);
    
    // 函数指针作为参数
    std::cout << "Calculate with different operations:" << std::endl;
    std::cout << "Add: " << Calculate(15, 5, Add) << std::endl;
    std::cout << "Multiply: " << Calculate(15, 5, Multiply) << std::endl;
    std::cout << "Subtract: " << Calculate(15, 5, Subtract) << std::endl;
    
    return 0;
}

函数指针数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>

// 计算器函数
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; }

// 操作名称
const char* GetOperationName(int index)
{
    static const char* names[] = {"Add", "Subtract", "Multiply", "Divide"};
    return (index >= 0 && index < 4) ? names[index] : "Unknown";
}

int main()
{
    // 函数指针数组
    int(*operations[])(int, int) = {Add, Subtract, Multiply, Divide};
    
    int a = 20, b = 4;
    
    std::cout << "Function pointer array example:" << std::endl;
    std::cout << "a = " << a << ", b = " << b << std::endl;
    
    for (int i = 0; i < 4; ++i)
    {
        int result = operations[i](a, b);
        std::cout << GetOperationName(i) << ": " << result << std::endl;
    }
    
    // 动态选择操作
    std::cout << "\nDynamic operation selection:" << std::endl;
    int choice = 2;  // 选择乘法
    if (choice >= 0 && choice < 4)
    {
        int result = operations[choice](a, b);
        std::cout << "Selected operation (" << GetOperationName(choice) << "): " << result << std::endl;
    }
    
    return 0;
}

成员函数指针

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>

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(const std::string& operation, int result)
    {
        std::cout << operation << " result: " << result << std::endl;
    }
    
    static int StaticAdd(int a, int b)
    {
        return a + b;
    }
};

int main()
{
    Calculator calc;
    
    // 成员函数指针的声明和使用
    int (Calculator::*memberFunc)(int, int) = &Calculator::Add;
    
    // 通过对象调用成员函数指针
    int result1 = (calc.*memberFunc)(10, 5);
    std::cout << "Member function pointer result: " << result1 << std::endl;
    
    // 通过指针调用成员函数指针
    Calculator* calcPtr = &calc;
    int result2 = (calcPtr->*memberFunc)(20, 8);
    std::cout << "Member function pointer via object pointer: " << result2 << std::endl;
    
    // 成员函数指针数组
    int (Calculator::*operations[])(int, int) = {
        &Calculator::Add,
        &Calculator::Subtract,
        &Calculator::Multiply
    };
    
    const char* operationNames[] = {"Add", "Subtract", "Multiply"};
    
    std::cout << "\nMember function pointer array:" << std::endl;
    for (int i = 0; i < 3; ++i)
    {
        int result = (calc.*operations[i])(15, 3);
        calc.PrintResult(operationNames[i], result);
    }
    
    // 静态成员函数指针(与普通函数指针相同)
    int(*staticFunc)(int, int) = &Calculator::StaticAdd;
    int staticResult = staticFunc(100, 200);
    std::cout << "Static member function result: " << staticResult << std::endl;
    
    return 0;
}

使用std::function的现代方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <functional>
#include <vector>

// 普通函数
int GlobalAdd(int a, int b)
{
    return a + b;
}

// 函数对象(仿函数)
class Multiplier
{
private:
    int m_Factor;
    
public:
    Multiplier(int factor) : m_Factor(factor) {}
    
    int operator()(int value) const
    {
        return value * m_Factor;
    }
};

class MathOperations
{
public:
    int Add(int a, int b) { return a + b; }
    
    static int StaticMultiply(int a, int b) { return a * b; }
};

void ProcessWithFunction(const std::vector<int>& values, const std::function<void(int)>& func)
{
    for (int value : values)
        func(value);
}

int main()
{
    std::cout << "=== std::function Examples ===" << std::endl;
    
    // 存储不同类型的可调用对象
    std::function<int(int, int)> operation;
    
    // 1. 普通函数
    operation = GlobalAdd;
    std::cout << "Global function: " << operation(10, 20) << std::endl;
    
    // 2. Lambda表达式
    operation = [](int a, int b) { return a - b; };
    std::cout << "Lambda: " << operation(30, 10) << std::endl;
    
    // 3. 函数对象
    Multiplier doubler(2);
    std::function<int(int)> unaryOp = doubler;
    std::cout << "Function object: " << unaryOp(15) << std::endl;
    
    // 4. 成员函数
    MathOperations math;
    operation = std::bind(&MathOperations::Add, &math, std::placeholders::_1, std::placeholders::_2);
    std::cout << "Member function: " << operation(5, 7) << std::endl;
    
    // 5. 静态成员函数
    operation = &MathOperations::StaticMultiply;
    std::cout << "Static member function: " << operation(6, 8) << std::endl;
    
    // std::function作为参数
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    std::cout << "\nProcessing with different functions:" << std::endl;
    
    ProcessWithFunction(numbers, [](int x) { std::cout << "Square: " << x * x << " "; });
    std::cout << std::endl;
    
    ProcessWithFunction(numbers, [](int x) { std::cout << "Double: " << x * 2 << " "; });
    std::cout << std::endl;
    
    return 0;
}

回调函数的实际应用

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>

// 事件系统示例
class EventSystem
{
public:
    using EventCallback = std::function<void(const std::string&)>;
    
private:
    std::vector<EventCallback> m_Callbacks;
    
public:
    void Subscribe(const EventCallback& callback)
    {
        m_Callbacks.push_back(callback);
    }
    
    void TriggerEvent(const std::string& eventData)
    {
        std::cout << "Triggering event: " << eventData << std::endl;
        for (const auto& callback : m_Callbacks)
        {
            callback(eventData);
        }
    }
};

// 排序比较函数示例
void SortingExample()
{
    std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
    
    std::cout << "Original: ";
    for (int num : numbers) std::cout << num << " ";
    std::cout << std::endl;
    
    // 使用函数指针进行排序
    std::sort(numbers.begin(), numbers.end(), [](int a, int b) { return a < b; });
    std::cout << "Ascending: ";
    for (int num : numbers) std::cout << num << " ";
    std::cout << std::endl;
    
    std::sort(numbers.begin(), numbers.end(), [](int a, int b) { return a > b; });
    std::cout << "Descending: ";
    for (int num : numbers) std::cout << num << " ";
    std::cout << std::endl;
}

// 策略模式示例
class DataProcessor
{
public:
    using ProcessingStrategy = std::function<void(std::vector<int>&)>;
    
private:
    ProcessingStrategy m_Strategy;
    
public:
    void SetStrategy(const ProcessingStrategy& strategy)
    {
        m_Strategy = strategy;
    }
    
    void ProcessData(std::vector<int>& data)
    {
        if (m_Strategy)
        {
            m_Strategy(data);
        }
    }
};

int main()
{
    std::cout << "=== Callback Applications ===" << std::endl;
    
    // 事件系统示例
    EventSystem eventSystem;
    
    // 订阅事件
    eventSystem.Subscribe([](const std::string& data) {
        std::cout << "  Handler 1 received: " << data << std::endl;
    });
    
    eventSystem.Subscribe([](const std::string& data) {
        std::cout << "  Handler 2 processed: " << data << std::endl;
    });
    
    eventSystem.TriggerEvent("User clicked button");
    eventSystem.TriggerEvent("File saved");
    
    std::cout << "\n=== Sorting Example ===" << std::endl;
    SortingExample();
    
    std::cout << "\n=== Strategy Pattern Example ===" << std::endl;
    DataProcessor processor;
    std::vector<int> data = {3, 1, 4, 1, 5, 9, 2, 6};
    
    std::cout << "Original data: ";
    for (int num : data) std::cout << num << " ";
    std::cout << std::endl;
    
    // 排序策略
    processor.SetStrategy([](std::vector<int>& vec) {
        std::sort(vec.begin(), vec.end());
        std::cout << "Applied sorting strategy" << std::endl;
    });
    processor.ProcessData(data);
    
    std::cout << "After sorting: ";
    for (int num : data) std::cout << num << " ";
    std::cout << std::endl;
    
    // 反转策略
    processor.SetStrategy([](std::vector<int>& vec) {
        std::reverse(vec.begin(), vec.end());
        std::cout << "Applied reversing strategy" << std::endl;
    });
    processor.ProcessData(data);
    
    std::cout << "After reversing: ";
    for (int num : data) std::cout << num << " ";
    std::cout << std::endl;
    
    return 0;
}

函数指针的性能考虑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <chrono>
#include <functional>

// 简单的数学函数
int SimpleAdd(int a, int b)
{
    return a + b;
}

// 内联函数
inline int InlineAdd(int a, int b)
{
    return a + b;
}

void PerformanceComparison()
{
    const int ITERATIONS = 100000000;
    
    // 直接函数调用
    auto start = std::chrono::high_resolution_clock::now();
    volatile int result1 = 0;
    for (int i = 0; i < ITERATIONS; ++i)
    {
        result1 += SimpleAdd(i, i + 1);
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto directTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 函数指针调用
    start = std::chrono::high_resolution_clock::now();
    int(*funcPtr)(int, int) = SimpleAdd;
    volatile int result2 = 0;
    for (int i = 0; i < ITERATIONS; ++i)
    {
        result2 += funcPtr(i, i + 1);
    }
    end = std::chrono::high_resolution_clock::now();
    auto ptrTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // std::function调用
    start = std::chrono::high_resolution_clock::now();
    std::function<int(int, int)> stdFunc = SimpleAdd;
    volatile int result3 = 0;
    for (int i = 0; i < ITERATIONS; ++i)
    {
        result3 += stdFunc(i, i + 1);
    }
    end = std::chrono::high_resolution_clock::now();
    auto stdFuncTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // Lambda调用
    start = std::chrono::high_resolution_clock::now();
    auto lambda = [](int a, int b) { return a + b; };
    volatile int result4 = 0;
    for (int i = 0; i < ITERATIONS; ++i)
    {
        result4 += lambda(i, i + 1);
    }
    end = std::chrono::high_resolution_clock::now();
    auto lambdaTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "Performance comparison (" << ITERATIONS << " iterations):" << std::endl;
    std::cout << "Direct call: " << directTime.count() << " ms" << std::endl;
    std::cout << "Function pointer: " << ptrTime.count() << " ms" << std::endl;
    std::cout << "std::function: " << stdFuncTime.count() << " ms" << std::endl;
    std::cout << "Lambda: " << lambdaTime.count() << " ms" << std::endl;
    
    std::cout << "\nResults (should be similar): " << std::endl;
    std::cout << "Direct: " << result1 << std::endl;
    std::cout << "Pointer: " << result2 << std::endl;
    std::cout << "std::function: " << result3 << std::endl;
    std::cout << "Lambda: " << result4 << std::endl;
}

int main()
{
    PerformanceComparison();
    return 0;
}

总结

  1. 函数指针本质:函数指针是将一个函数赋值给一个变量的方法
  2. 语法格式返回类型(*指针名)(参数列表)
  3. 使用场景
    • 回调函数
    • 事件处理
    • 策略模式
    • 算法的自定义比较函数
  4. 现代替代方案
    • std::function:更灵活,可以存储各种可调用对象
    • Lambda表达式:更简洁的语法
  5. 性能考虑
    • 直接函数调用最快
    • 函数指针有轻微开销
    • std::function开销较大但更灵活
  6. 最佳实践:在需要灵活性时使用std::function,在性能关键场景使用原始函数指针
updatedupdated2025-09-202025-09-20