首页 文章

为什么Qt信号不是常数

提问于
浏览
6

Qt使用signals and slots进行对象通信 . 信号通常被声明为成员函数,然后Qt MOC生成该函数的定义 .

我想了解的是为什么信号不是const成员函数?

编辑:我希望信号不会修改发件人,这就是问题的原因 .

3 回答

  • 9

    我希望信号不会修改发件人

    信号(如generated by the MOC)不直接修改类实例的成员 . 但是,生成的代码会传递一个 this 指针,供(潜在)插槽使用 . 因此,连接的插槽可以改变信号的发送方 .

    因此技术原因是,如果信号是 const ,则需要所有插槽实现只调用发送方上的 const 类成员,以便编译代码而不会出错 .

    在代码安全方面,将信号实现为非 const 类成员是一个可以理解的决定 . 在许多情况下,它仍然感觉不自然(例如,如果在同一类中实现的连接槽是 const ,或者连接的槽完全属于另一个对象) .

  • 0

    Nothing prevents a Qt signal to be const AFAIK (用Qt5.9测试) . IInspectable的答案是不正确的 .

    下面是我做的测试,表明它仍然可以

    • 将const信号连接到同一实例中的非const插槽
    • sender() 上调用非const方法 .

    我的测试类,编译精细(gcc):

    // Stupid class to test the emit of a const-signal
    class Test : public QObject
    {
        Q_OBJECT
    
    public:
        // Connect in the constructor from this instance to this instance
        explicit Test(QObject *parent = nullptr) : QObject(parent) {
            connect(this, &Test::valueChanged, this, &Test::updateString);
        }
    
        // To test a non-const method call
        void nonConstFoo() {
            setObjectName("foo"); // I modify the 'this' instance
        }
    
        // To test emit of a non-const signal from a const-method
    //    void constFoo() const {
    //        emit fooSignal(); // --> FAIL at compile time
    //    }
    
    public slots:
        void setValue(int value) {
            m_value = value;
            emit valueChanged(value);
        }
    
        void updateString(int value) {
            m_string = QString::number(value); // I modify the 'this' instance
            nonConstFoo(); // I modify the 'this' instance through a non-const call
    
            auto s = sender();
            s->setObjectName("mutated name"); // I modify the 'sender' instance
    
            qDebug() << "Updated string" << m_string;
        }
    
    signals:
        void valueChanged(int) const; // The signal is const
        void fooSignal(); // Non-const signal
    
    private:
        int m_value;
        QString m_string;
    };
    

    以下是MOC为信号生成的代码:

    // SIGNAL 0
    void Test::valueChanged(int _t1)const
    {
        void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
        QMetaObject::activate(const_cast< Test *>(this), &staticMetaObject, 0, _a);
    }
    
    // SIGNAL 1
    void Test::fooSignal()
    {
        QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
    }
    

    我们可以看到Qt在此使用const_cast,所以一切都会正常工作 .


    在我看来,默认情况下信号不是const的原因是这需要MOC在 your 标头中为 your signal(== class-method)定义添加一个const,因此修改你的源代码 .

    我想通过在宏中包含每个信号定义是可行的,但想象编码器和读者的痛苦 . 我没有看到Qt(也不是你)将你的信号声明为const的任何好处,这将需要你和Qt的更多工作 .

    But 您可能需要将它们声明为const . 就像你想从const方法发出它们一样 . 你可以自由地这样做 .

  • 3

    信号可以是const,实际上如果你想从const函数发出一个信号,它必须是一个const信号,但在槽端,它不需要是const . 当我用const pures重新实现抽象类时,我已经不必这样使用mutable了 .

相关问题