连接到基类'在子类中覆盖它时发出信号

时间:2014-12-14 19:09:07

标签: c++ qt

Qt提供QSpinBox,这是一个提供信号的远QObject衍生物:

class QSpinBox:
    public /* ... */ QObject {

    signals:
        void valueChanged(int i);
};

从这个旋转框导出时,我可能会为此信号提供一个覆盖,以发出一些美化版本的值:

class MySpinBox:
    public QSpinBox {

    private slots:
        void originalValueChanged(int i) {
            /* Beautify */
            emit valueChanged( 42 * i );
        }

    signals:
        void valueChanged(int myPersonalI);
};

这似乎完全正常:信号MySpinBox::valueChanged(int)隐藏了继承的信号。唯一缺少的是将继承的QSpinBox::valueChanged(int)连接到私有广告位MySpinBox::originalValueChanged(int)

虽然可以使用 new 信号和插槽语法:

connect(
    static_cast<QSpinBox *>(this), &QSpinBox::valueChanged,
    this, &MySpinBox::originalValueChanged);

我不确定这是允许还是敏感,也不知道如何使用传统的基于字符串的信号/插槽语法连接信号。使用后者,插槽明显连接到MySpinBox::originalValueChanged(int)信号,这显然不是预期的。

目的

上面的例子简化为我认为我面临的问题。要理解为什么我遇到问题并且可能引导我摆脱这个(假装的)破坏的设计,想一下QDoubleSpinBox导数来输入一些物理量,例如:速度。用户可能希望在某个首选单元中输入此内容,该单元可能是km/hmph。为了从应用程序中获取单位转换逻辑,我编写了一个新的小部件,派生自QWidget并且只包含QDoubleSpinBox。然后我实现了通常的旋转框方法(setMinimumsetSingleStep等),它们采用SI维度中的相应属性(即,在此示例中为m/s),将它们转换为某个选定的单位然后配置下双旋转框。

setValue(double)将其参数转换为用户的单位并将其传递给下级。反过来,只要下方旋转框发出valueChanged(double),就会发出valueChanged信号,但数量会转换回SI维度。

所以最后我修补了没有使用劣质旋转框组成QWidget衍生物,而是从QDoubleSpinBox得到并重新实现。

优点和缺点显示部分清楚,包括已经由@Pavel Strakhov解释的问题。实际上,编写窗口小部件可以让我摆脱被调用的错误继承的方法(由于不是虚拟的),代价是包装QWidget。所以作为一个中间步骤,我正在修补从QDoubleSpinBox派生私人。这肯定不是GUI应用程序中的资源问题,但对我而言,这也是学习和修补的问题。

然后我偶然发现了信号,想知道Qt会怎么想。

1 个答案:

答案 0 :(得分:0)

请注意,QSpinBox::valueChanged不是虚拟的,这意味着,如果MySpinBox指针中存储了QSpinBox*的实例并调用其valueChanged方法,则QSpinBox::valueChanged将被执行而不是MySpinBox::valueChanged。 Qt内部函数肯定会有QSpinBox*指向实例的指针。这种不一致可能是错误的根源。非虚函数不应在子类中重新定义,您不应该这样做。 Qt内置类都没有使用这种重新定义。子类通常会添加新信号,不会触及基类信号。