函数指针与回调函数(c++)

函数和函数指针

cpp 复制代码
void hello(int x) {
    std::cout << "Hello " << x << std::endl;
}

这个函数叫 hello,它有一个地址(就像房间有门牌号一样)。

我们想用一个变量来保存这个地址,这个变量就是"函数指针"。

给函数指针赋值

cpp 复制代码
void hello(int x) {
    std::cout << "Hello " << x << std::endl;
}

int main() {
    void (*ptr)(int);     // 定义一个函数指针
    ptr = hello;          // 把函数 hello 的地址赋给 ptr

    ptr(5);               // 调用 ptr 指向的函数,等价于 hello(5)
    return 0;
}

✅ 关键点

hello 是函数名,它本身就表示"函数的地址"

ptr = hello; 就是把 hello 的地址存到 ptr 中

ptr(5); 就是"调用 ptr 指向的那个函数",和 hello(5) 效果一样

加上 typedef

现在我们觉得 void (*ptr)(int) 太长、太难写,想给它起个简单名字。

cpp 复制代码
typedef void (*Callback)(int);

这行代码的意思是:

"从现在起,Callback 是一个类型别名,它等价于 void (*)(int) 这种函数指针类型。"

用新名字来定义变量

cpp 复制代码
#include <iostream>

// 定义一个新类型:Callback
typedef void (*Callback)(int);

// 一个符合这个类型的函数
void greet(int x) {
    std::cout << "Hello: " << x << std::endl;
}

int main() {
    Callback ptr;      // 等价于 void (*ptr)(int);
    ptr = greet;       // 把函数地址赋给 ptr
    ptr(5);            // 调用 greet(5)
    return 0;
}

回调函数

cpp 复制代码
#include <iostream>

// 1. 定义回调函数的类型:返回 void,参数是 int
typedef void (*Callback)(int);

// 2. 一个普通函数,我们将用它作为回调
void myCallback(int x) {
    std::cout << "回调被调用,x = " << x << std::endl;
}

// 3. 主函数:它接收一个"回调函数"作为参数
void doWork(int data, Callback cb) {
    // 做一些工作...
    std::cout << "正在处理数据..." << std::endl;

    // 工作完成,调用回调函数
    cb(data);  // 这就是"回调":调用你传进来的函数
}

// 4. 主程序
int main() {
    // 调用 doWork,并把 myCallback 作为回调传进去
    doWork(100, myCallback);

    return 0;
}

再举一个简单的例子:

cpp 复制代码
#include <iostream>

// 1. 定义一个回调函数类型(可选,用 typedef 简化)
//typedef void (*Callback)(int);

// 或者用更现代的写法(C++11 起):
using Callback = void (*)(int);

// 2. 一个实际的回调函数(打印数字)
void printNumber(int value) {
    std::cout << "收到数值: " << value << std::endl;
}

// 3. 一个接受回调函数的函数
void doSomething(int x, Callback callback) {
    std::cout << "正在处理..." << std::endl;
    // 做一些事情...
    
    // 调用回调函数
    callback(x);
}

// 4. 主函数
int main() {
    // 传递 printNumber 作为回调
    doSomething(42, printNumber);

    return 0;
}

通过function<>的例子:

cpp 复制代码
#include <iostream>
#include <functional>

// 使用别名简化类型(可读性更好)
using Callback = std::function<void(int)>;

void doSomething(int x, const Callback& callback) {
    std::cout << "正在处理..." << std::endl;
    
    // 可选:检查 callback 是否有效(防止空调用)
    if (callback) {
        callback(x);
    } else {
        std::cerr << "警告:回调函数为空!" << std::endl;
    }
}

int main() {
    doSomething(42, [](int value) {
        std::cout << "Lambda 回调: " << value << std::endl;
    });

    return 0;
}

std::function<void(int)>

是一个 C++ 标准库提供的"通用可调用对象包装器",它可以保存、复制、调用任何"和 void(int) 类型匹配的可调用对象"。

cpp 复制代码
#include <iostream>
#include <functional>

// 定义一个类型别名,简化写法
using Callback = std::function<void(int)>;

// 1. 普通函数
void normal_func(int x) {
    std::cout << "普通函数: " << x << std::endl;
}

// 2. Lambda 表达式(匿名函数)
auto lambda = [](int x) {
    std::cout << "Lambda: " << x << std::endl;
};

// 3. 函数对象(仿函数)
struct Functor {
    void operator()(int x) {
        std::cout << "函数对象: " << x << std::endl;
    }
};

int main() {
    Callback cb;

    // ✅ 都可以赋值给 std::function<void(int)>
    cb = normal_func;     // 普通函数
    cb(1);

    cb = lambda;          // Lambda
    cb(2);

    cb = Functor();       // 函数对象
    cb(3);

    return 0;
}