最近在论坛上看到了这个方面的问题,详见这里。
随后浅浅地学习了一下子,看到了Qt官方论坛上给出的说明,觉得C++11的functional连接方法还是比Qt4既有的宏连接方法有很大不同。
官方论坛的文档:http://doc.qt.io/qt-5/signalsandslots-syntaxes.html
我们在一个简单的Dialog中,安排如下几个信号与槽:
- class SSTest : public QDialog
- {
- //...
- signals:
- void sgn_test1(QByteArray arr);
- void sgn_test2(int n);
- void sgn_test2(QString s);
- void sgn_test3(double c, double d);
- public slots:
- void slt_1();
- void slt_2(double v);
- void slt_2(QString s);
- void slt_3(int s);
- //...
- };
- //cpp
- //......
- void SSTest::slt_1()
- {
- qDebug()<<"SSTest::slt_1()";
- }
- void SSTest::slt_2(double v)
- {
- qDebug()<<"SSTest::slt_2(double v):"<<v;
- }
- void SSTest::slt_2(QString s)
- {
- qDebug()<<"SSTest::slt_2(QString s):"<<s;
- }
- void SSTest::slt_3(int s)
- {
- qDebug()<<"SSTest::slt_3(int s):"<<s;
- }
而后,在构造函数中,直接采用文档所述方法,进行连接.
此类情况,对应 sgn_test1、slt_1
直接连接即可:
- connect(this, &SSTest: :sgn_test1, this, &SSTest: :slt_1);
- connect(this, &SSTest: :sgn_test3, this, &SSTest: :slt_3);
编译OK,说明,槽的参数可以比信号少。并且,存在着隐含参数转换:
第一行,QByteArray arr 参数被忽略了,因为槽没有参数。
第二行,double c, double d 两个参数,第二个被忽略了,因为槽只有一个int参数。第一个参数被隐含转换。
测试:
- emit sgn_test1(QByteArray());
- emit sgn_test3(1.7, 2.2);
输出:
- SSTest::slt_1()
- SSTest::slt_3(int s): 1
但是,如果我们把不支持隐含转换的信号与槽连接,则会错误:
- connect(this, &SSTest: :sgn_test1, this, &SSTest: :slt_3);
QByteArray 无法转换为 int, 因此无法通过编译(具体错误与编译器相关):
- C: \...\qobjectdefs_impl.h: 299 : error: 'QByteArray::operator QNoImplicitBoolCast() const'is private within this context enum {
- value = sizeof(test(dummy())) == sizeof(int)
- };~~~~~ ^ ~~~~~~~~~
我们试着简单连接sgn_test3和slt_2
- connect(this, &SSTest: :sgn_test3, this, &SSTest: :slt_2);
与估计的一样,无法编译:
- C: \...\sstest.cpp: 15 : error: no matching
- function
- for call to 'SSTest::connect(SSTest*, void (SSTest::*)(double, double), SSTest*, <unresolved overloaded function type>)'connect(this, &SSTest: :sgn_test3, this, &SSTest: :slt_2); ^
此时,我们采用下面这两种方式之一,即可:
- connect (
- this
- ,&SSTest::sgn_test3,
- this
- ,
- static_cast
- <
- void
- (SSTest::*)(
- double
- )>(&SSTest::slt_2));
或者(C++14以上)
- connect(this, &SSTest: :sgn_test3, this, qOverload < double > ( & SSTest: :slt_2));
这等于强制指定了连接方法。测试:
- emit sgn_test3(1.7, 2.2);
输出:
- SSTest: :slt_2(double v) : 1.7
有了上面的经验,面对重载已经不怕了:
- //C++14风格同时指定信号、槽的参数表
- connect(this, qOverload < QString > ( & SSTest: :sgn_test2), this, qOverload < QString > ( & SSTest: :slt_2));
- //static_cast风格同时指定信号、槽的参数表
- connect(this, static_cast < void(SSTest: :*)(int) > ( & SSTest: :sgn_test2), this, static_cast < void(SSTest: :*)(double) > ( & SSTest: :slt_2));
- //信号重载,连接到单一的槽
- connect(this, static_cast < void(SSTest: :*)(int) > ( & SSTest: :sgn_test2), this, &SSTest: :slt_1);
测试:
- emit sgn_test2("haha!");
- emit sgn_test2(1);
输出:
- SSTest::slt_2(QString s): "haha!"
- SSTest::slt_2(double v): 1
- SSTest::slt_1()
当然,既然Qt5采用的是functional机制,一定可以用lambda:
- int p = 100;
- connect(this, &SSTest: :sgn_test3, [ = ](double a, double b) - >void {
- qDebug() << (p * a + b);
- });
测试:
- emit sgn_test3(1.7, 2.2);
输出:
- 172.2
传统的Qt4 Signal-Slot宏连接兼容性好,但是没有编译时检查,往往会由于笔误,产生预料之外的效果。现在,有了C++11 functional的支持,可以借助编译器进行严格的类型检查,明显是有利于调试了。
来源: http://blog.csdn.net/goldenhawking/article/details/78766676