C++中如何实现回调的方法示例

C++中实现回调的方法有多种,下面介绍两种常见的实现方式。

方式一:函数指针

通过函数指针实现回调,需要定义一个函数指针类型,将回调函数与函数指针进行绑定,然后在合适的时机调用函数指针即可。

示例1

定义一个函数指针类型,函数原型为:

typedef void (*MyCallbackFunc) (int arg1, int arg2);

其中,第一个参数表示回调函数的返回值类型,第二个参数表示回调函数的参数个数及类型。

定义一个类,成员变量为函数指针类型,成员函数用于设置和触发回调函数。

class MyClass {
public:
    void SetCallback(MyCallbackFunc callback) {
        _callback = callback;
    }

    void DoSomething() {
        // 判断回调函数是否为空指针
        if (_callback != nullptr) {
            // 调用回调函数
            _callback(10, 20);
        }
    }

private:
    MyCallbackFunc _callback; // 函数指针类型成员变量
};

客户端需要实现一个回调函数,并将其与类的函数指针绑定。示例代码如下:

void MyCallback(int arg1, int arg2) {
    // do something
}

int main() {
    MyClass myClass;
    myClass.SetCallback(MyCallback);
    myClass.DoSomething();
    return 0;
}

在main函数中生成一个MyClass对象,调用SetCallback函数将MyCallback函数与函数指针绑定,然后调用DoSomething函数触发回调函数。

示例2

使用STL中的函数对象(function object)代替函数指针实现回调。function object 是一个可调用的对象,可以表示函数指针、lambda表达式、成员函数指针等。

定义一个函数对象类型,函数原型与上一个示例中的函数指针类型相同。

using MyCallbackFunc = std::function<void(int, int)>;

使用STL中的std::function模板类代替函数指针类型。

重写MyClass类,将函数指针类型的成员变量改为函数对象类型。

class MyClass {
public:
    void SetCallback(MyCallbackFunc callback) {
        _callback = callback;
    }

    void DoSomething() {
        // 判断回调函数是否为空
        if (_callback) {
            _callback(10, 20);
        }
    }

private:
    MyCallbackFunc _callback;
};

客户端代码与示例1中的相同。

方式二:虚函数

使用虚函数也可以实现回调。

示例1

定义一个基类,将回调函数声明为虚函数。

class MyBaseClass {
public:
    virtual void MyCallback(int arg1, int arg2) { }
};

派生一个子类MyClass,在其内部实现回调函数。

class MyClass : public MyBaseClass {
public:
    void DoSomething() {
        // ...

        // 判断回调函数是否为空
        if (_callback) {
            _callback(10, 20);
        }

        // ...
    }

private:
    void MyCallback(int arg1, int arg2) override {
        // do something
    }
};

在MyClass类中调用MyCallback函数即可触发回调。

示例2

使用虚函数时,可以使用接口(interface)定义回调函数,客户端需要实现接口中的回调函数。

定义一个接口,包含所有需要实现的回调函数。

class IMyCallback {
public:
    virtual ~IMyCallback() { }
    virtual void MyCallback(int arg1, int arg2) { } // 回调函数声明
};

重新定义MyClass类,将回调函数类型改为IMyCallback接口。

class MyClass {
public:
    void SetCallback(IMyCallback* callback) {
        _callback = callback;
    }

    void DoSomething() {
        // ...

        if (_callback) {
            _callback->MyCallback(10, 20);
        }

        // ...
    }

private:
    IMyCallback* _callback;
};

客户端需要实现MyCallback函数,代码如下:

class MyCallbackImpl : public IMyCallback {
public:
    void MyCallback(int arg1, int arg2) override {
        // do something
    }
};

int main() {
    MyClass myClass;
    MyCallbackImpl callbackImpl;
    myClass.SetCallback(&callbackImpl);
    myClass.DoSomething();
    return 0;
}

在main函数中生成一个MyClass对象,同时生成一个MyCallbackImpl对象实现接口中的回调函数,然后调用SetCallback函数将MyCallbackImpl对象的指针作为参数传入,最后调用DoSomething函数触发回调函数。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中如何实现回调的方法示例 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++程序的执行顺序结构以及关系和逻辑运算符讲解

    让我来为你详细讲解一下C++程序的执行顺序结构以及关系和逻辑运算符讲解的攻略。 C++程序的执行顺序结构 在C++程序中,程序的执行顺序遵循自上而下的顺序结构。也就是说,程序会首先执行第一条语句,然后接着执行第二条语句,以此类推,直到程序执行完所有语句为止。 下面是一个简单的示例,说明C++程序的执行顺序结构: #include <iostream&g…

    C 2023年5月23日
    00
  • 详解C++内存的代码区,全局区,栈区和堆区

    首先我们来了解一下 C++ 内存分区的四个部分:代码区、全局区、栈区和堆区。 代码区 代码区是用于存放程序的可执行代码,是只读的,它的大小在程序编译时就已经确定了。在代码区中,每个函数都有一个入口地址,这些入口地址按照函数声明的顺序保存在函数表中。 全局区 全局区用于全局变量和静态变量的存储,它在程序运行前就已经分配好了固定的内存空间,程序结束时才会被释放。…

    C 2023年5月24日
    00
  • SpringBoot整合Redis入门之缓存数据的方法

    下面是 “SpringBoot整合Redis入门之缓存数据的方法” 的完整攻略。 简介 在高并发访问下,数据库成为了性能瓶颈,为了解决这个问题,我们可以加入缓存来减轻数据库的压力,提高网站的响应速度。Redis作为一个高性能的内存数据库,被广泛应用于缓存系统中。在SpringBoot中,通过RedisTemplate来实现redis的缓存数据。 环境准备 首…

    C 2023年5月23日
    00
  • JS实现的合并多个数组去重算法示例

    JS实现的合并多个数组去重算法示例,主要分为以下几个步骤: 1.准备合并的多个数组 首先需要准备多个要合并的数组,可以使用数组字面量或者数组构造函数来创建一些示例数组。例如: const arr1 = [1, 2, 3]; const arr2 = [3, 4, 5]; const arr3 = [6, 7, 8]; 2.合并多个数组 接下来需要将多个数组合…

    C 2023年5月23日
    00
  • boost.asio框架系列之buffer函数

    Boost.Asio框架系列之buffer函数 在Boost.Asio框架中,boost::asio::buffer()函数的主要作用是创建一个缓冲区,以便在套接字(Socket)和其他数据源之间传输数据。在进行异步操作时,使用缓冲区管理和传输数据是很常见的。boost::asio::buffer()函数支持很多不同的数据类型,它支持以下数据类型: 基础数据…

    C 2023年5月23日
    00
  • C++ vector的简单实现

    C++ vector的简单实现 在C++中,vector是一种非常常用的容器,它能够动态地保存一组元素(比如整数、浮点数以及自定义类型等)。在本文中,我们将分步讲解如何实现一个简单的vector。 步骤1:定义类和变量 我们首先要定义一个vector类,它可以保存任意类型的元素,使用template<typename T>来定义: templat…

    C 2023年5月23日
    00
  • ubuntu系统vscodeC++编译环境配置与使用方式

    下面为你详细讲解“ubuntu系统vscodeC++编译环境配置与使用方式”的完整攻略。 一、安装和配置C++编译环境 1. 安装GCC和G++编译器 在终端执行以下命令来安装GCC和G++编译器: sudo apt install build-essential 2. 安装CMake 在终端执行以下命令来安装CMake: sudo apt install …

    C 2023年5月23日
    00
  • C语言实现扫雷小游戏详解

    C语言实现扫雷小游戏详解 简介 扫雷游戏是一款激动人心的游戏,它的目的是在不踩到地雷的情况下清除地图上的所有方块。C语言实现扫雷小游戏可以通过练习和编程技能的提高,学习C语言编程方法和数据结构。 游戏说明 游戏开始,出现一个n*n的方块图案,里面随机布置了一些“地雷”。然后,玩家需要依靠自己的智慧,打开不知道有没有地雷的方块,同时用数字来描述周围方块中地雷的…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部