• Qt5信号与槽C++11风格连接简介


    最近在论坛上看到了这个方面的问题,详见这里。 
    随后浅浅地学习了一下子,看到了Qt官方论坛上给出的说明,觉得C++11的functional连接方法还是比Qt4既有的宏连接方法有很大不同。 
    官方论坛的文档:http://doc.qt.io/qt-5/signalsandslots-syntaxes.html

    1.实验代码

    我们在一个简单的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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    而后,在构造函数中,直接采用文档所述方法,进行连接.

    2.各类情况测试

    2.1. 信号、槽均无重载

    此类情况,对应 sgn_test1、slt_1 
    直接连接即可:

    connect (this,&SSTest::sgn_test1,this,&SSTest::slt_1);
    connect (this,&SSTest::sgn_test3,this,&SSTest::slt_3);
    • 1
    • 2

    编译OK,说明,槽的参数可以比信号少。并且,存在着隐含参数转换: 
    第一行,QByteArray arr 参数被忽略了,因为槽没有参数。 
    第二行,double c, double d 两个参数,第二个被忽略了,因为槽只有一个int参数。第一个参数被隐含转换。 
    测试:

        emit sgn_test1(QByteArray());
        emit sgn_test3(1.7,2.2);
    • 1
    • 2

    输出:

    SSTest::slt_1()
    SSTest::slt_3(int s): 1
    • 1
    • 2

    但是,如果我们把不支持隐含转换的信号与槽连接,则会错误:

    connect (this,&SSTest::sgn_test1,this,&SSTest::slt_3);
    • 1

    QByteArray 无法转换为 int, 因此无法通过编译(具体错误与编译器相关):

    C:...qobjectdefs_impl.h:299: error: 'QByteArray::operator QNoImplicitBoolCast() const' is private within this context
             enum { value = sizeof(test(dummy())) == sizeof(int) };
                                  ~~~~~^~~~~~~~~~
    • 1
    • 2
    • 3

    2.2. 信号唯一,槽重载

    我们试着简单连接sgn_test3和slt_2

    connect (this,&SSTest::sgn_test3,this,&SSTest::slt_2);
    • 1

    与估计的一样,无法编译:

    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);
                                                          ^
    • 1
    • 2
    • 3

    此时,我们采用下面这两种方式之一,即可:

    connect (this,&SSTest::sgn_test3,this,static_cast<void(SSTest::*)(double)>(&SSTest::slt_2));
    • 1

    或者(C++14以上)

    connect (this,&SSTest::sgn_test3,this,qOverload<double>(&SSTest::slt_2));
    • 1

    这等于强制指定了连接方法。测试:

    emit sgn_test3(1.7,2.2);
    • 1

    输出:

    SSTest::slt_2(double v): 1.7
    • 1

    2.3. 信号重载、槽重载

    有了上面的经验,面对重载已经不怕了:

    //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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试:

    emit sgn_test2("haha!");
    emit sgn_test2(1);
    • 1
    • 2

    输出:

    SSTest::slt_2(QString s): "haha!"
    SSTest::slt_2(double v): 1
    SSTest::slt_1()
    • 1
    • 2
    • 3

    2.4. 更灵活的lambda表达式

    当然,既然Qt5采用的是functional机制,一定可以用lambda:

    int p = 100;
    connect (this,&SSTest::sgn_test3,[=](double a ,double b)->void{
        qDebug()<<(p*a+b);
    });
    • 1
    • 2
    • 3
    • 4

    测试:

    emit sgn_test3(1.7,2.2);
    • 1

    输出:

    172.2
    • 1

    3. 总结

    传统的Qt4 Signal-Slot宏连接兼容性好,但是没有编译时检查,往往会由于笔误,产生预料之外的效果。现在,有了C++11 functional的支持,可以借助编译器进行严格的类型检查,明显是有利于调试了。

    http://blog.csdn.net/goldenhawking/article/details/78766676

  • 相关阅读:
    Zookeeper环境搭建
    Zookeeper介绍
    相关错题
    数据库前三章测试题
    数据库相关练习题
    SQL语句操作数据
    用表组织数据
    创建和管理SQL Server数据库
    登陆数据库
    C#部分试题实例
  • 原文地址:https://www.cnblogs.com/findumars/p/8260905.html
Copyright © 2020-2023  润新知