IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++/Qt 回调函数(C函数回调、类函数回调、信号回调) -> 正文阅读

[C++知识库]C++/Qt 回调函数(C函数回调、类函数回调、信号回调)

实验框架说明

编译运行环境

Ubuntu Kylin 20.04.3 LTS??????? +??????? Qt 5.12.8??????? +??????? GCC

Child类

首先声明一个子类Child,为了之后能够支持Qt信号量,让他继承QObject,因为我有多线程需要,QThread继承QObject,因此这里直接继承QThread。

class Child:public QThread
{
    Q_OBJECT
public:
    explicit Child(){
//        connect(this, &Child::SN_Req, this, [this](void in()){in();});
        connect(this, &Child::SN_Req2, this, [this](std::function<int()> in){in();});
        connect(this, &Child::SN_Req3, this, [this](std::function<void()> in){in();});
//        SN_Req([](){qDebug() << "SN_Req CallBack1";});
//        SN_Req([this](){qDebug() << "SN_Req CallBack2";});
    }
    ~Child(){;}

    void func1();
    void func3(void in()){in();};
    void func4(std::function<void()> in){if (in) in();};

signals:
//    void SN_Req(void in());
    void SN_Req2(std::function<int()> in);
    void SN_Req3(std::function<void()> in);
};

Parent类

再声明一个parent类,有一个Child类成员。

class Parent : public QObject
{
    Q_OBJECT
public:
    explicit Parent(QObject *parent = nullptr);

//    void func5(void Child::func2()){in();};
    int val;
private:
    Child a;
};

?

函数回调

我们看Child里面的func3、func4,这两种都是用于函数回调的例子。

所谓回调函数,其实就是把函数作为指针参数传进调用的函数里,然后在调用的函数里,在调用这个指针函数。看着非常复杂对吧,其实完全不用去考虑什么指针函数、函数指针,直接把函数整个放进去就行。

void func3(void in()){in();};

或者使用C++11标准里的function:

void func4(std::function<void()> in){if (in) in();};

这两者在函数回调里面用法大概是没什么区别的,但到了下面信号回调就不一样了。

C函数回调

我们在main函数里实例化Child,并在main函数前定义一个用于回调的C函数:


void funco1(){
    qDebug() << "normal func";
}
int main(int argc, char *argv[])
{
    Child a1;
    Parent t;
    a1.func3(&funco1);
    a1.func4(&funco1);
    a1.func3([](){qDebug() << "lambda func3";});
    a1.func4([](){qDebug() << "lambda func4";});
//    a1.func3(&a1.func1);
    return 0;
}

可以看到,无论是普通的C函数还是不带this的lambda函数都一视同仁,func3、func4都很好地支持了。

类成员函数回调

但是如果你想把a1的func1传进去却不行,因为C++类成员函数跟C函数是不一样的,具体是关于地址动态和固定的问题,有兴趣可以单独去了解。

//    a1.func3(&a1.func1);

但是你可以在Parent的函数里面把带this的lambda传进去,比如在构造函数里:

//    a.func3([this](){qDebug() << b.val;});
    a.func4([this](){qDebug() << b.val;});

看到没,这里就有区别了,fun3是不能传带this的,但func4可以。

信号回调

现在如果我想发射一个信号,让接收到这个信号的类在执行完之后,调用这个回调函数,要怎么做?

这里就只能采取类似func4的方法:

signals:
//    void SN_Req(void in());
    void SN_Req3(std::function<void()> in);

SN_Req虽然在编写代码的时候不会警告,但编译是无法通过的。

然后需要在槽里面回调这个函数:

        connect(this, &Child::SN_Req3, this, [this](std::function<void()> in){in();});

在Parent类里面调用这个信号也是没有限制的,可以将this捕获:

    a.SN_Req3([this](){qDebug() << val;});

但要注意,如果两个类运行的线程不一样的话,信号槽不是直连,就需要注册这个类型:

qRegisterMetaType< std::function<void()> >("std::function<void()>");

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:27:40  更:2022-04-07 22:29:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:59:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码