0
点赞
收藏
分享

微信扫一扫

C++/Qt 回调函数(C函数回调、类函数回调、信号回调)

野见 2022-04-06 阅读 61
qtc++

实验框架说明

编译运行环境

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(
a1.func4(
a1.func3([](){qDebug() << "lambda func3";});
a1.func4([](){qDebug() << "lambda func4";});
// a1.func3(
return 0;
}

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

类成员函数回调

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

//    a1.func3(

但是你可以在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()>");
举报

相关推荐

0 条评论