使用继承信号的Q_PROPERTY NOTIFY的解决方法

Workaround to Q_PROPERTY NOTIFY with inherited signal

本文关键字:PROPERTY NOTIFY 解决 方法 继承 信号      更新时间:2023-10-16

已知继承信号不能用作Q_PROPERTY NOTIFY er (https://bugreports.qt.io/browse/QTBUG-7684)。作为一种变通方法,我在派生类中使用了一个额外的信号,当基信号被触发时,它会被触发。基类:

class Base : public QObject {
    Q_OBJECT
signals:
    void mySignal();
};

对于派生类:

class Derived : public Base {
    Q_OBJECT
    Q_PROPERTY(int myPropery READ getMyProperty NOTIFY mySignal_inherited)
public:
    Derived(){
        connect(this, SIGNAL(mySignal()), this, SIGNAL(mySignal_inherited()));
    }
    int getMyProperty(){ return myProperty; }
signals:
    void mySignal_inherited(); ///< DO NOT USE EXPLICITLY
private:
    int myProperty;
};

是否有更好/更优雅的解决方案?

为了防止别人显式地使用这个信号,你可以做的一件事是将它声明为私有的,除了moc-run。这样就没有人可以使用这个信号:

signals:
#ifndef Q_MOC_RUN//this will be defined if moc runs, thus skipped
private:
#endif
    void mySignal_inherited(); ///< DO NOT USE EXPLICITLY

另一个选项,取决于你如何使用Base,将是使用一个纯虚拟信号:

class Base : public QObject {
    Q_OBJECT
signals:
    virtual void mySignal() = 0;
};
class Derived : public Base {
    //...
signals:
    void mySignal() final;//mark as final
};

WARNING: Signals不是virtual。您不能覆盖信号。然而,实现是可能的。这就是为什么我在这里使用final,以防止有人覆盖它。代码将生成相应的警告,但只要您知道这个事实,它就能正常工作。

请注意,如果基类有Q_OBJECT宏,我还没有尝试过纯虚拟信号是否有效!如果你的基类被声明为一个插件接口(比如:https://doc.qt.io/qt-5/qtwidgets-tools-echoplugin-example.html#echointerface-class-definition)