Qt:子类中无法识别的继承信号

时间:2013-05-17 08:43:04

标签: c++ qt inheritance signals

我创建了一个基类,为其所有子类提供公共信号:

#include <QWidget>

namespace Dino {

/**
 * @brief Base class for all single-value settings editors
 *
 * Provides a valueChanged() signal that can be used to propagate changes to
 * values up to the MainWindow
 */
class TypeEditor : public QWidget
{
    Q_OBJECT
public:
    explicit TypeEditor(QWidget *parent = 0):QWidget(parent){}

signals:
    void valueChanged();    
};

} // namespace Dino

在子类中,我想让这个信号可用,但是也要定义一个具有相同名称但不同参数的更具体的信号:

#include "ui/typeeditor.h"

namespace Dino {

class BoolEditor : public TypeEditor
{
    Q_OBJECT
public:
    explicit BoolEditor(QWidget* parent = 0):TypeEditor(parent){}

signals:
    void valueChanged(bool value);

public slots:
    void setValue(bool value)
    {
        emit valueChanged(value);
        emit valueChanged();
    }
};

} // namespace Dino

这个想法是,当只知道基类类型时,可以使用广义信号,这表示值已经发生了变化。当确切的子类类型已知时,另一个信号可用,它告诉新值。

现在,当我尝试编译时,我在emit valueChanged()上收到错误,指出没有名为Dino::BoolEditor::valueChanged()的函数。

当我将基类中的信号重命名为其他可用的信号时,这似乎是信号过载的问题。我会对此感兴趣。是否有一些我不知道的设计要求会阻止我在子类中重载信号,或者我只是遗漏了代码中的某些内容?

4 个答案:

答案 0 :(得分:2)

信号只是一个受保护的功能。你不能像这样重载基类函数

有关详细信息,请参阅this question

答案 1 :(得分:1)

这是C ++中的重载方法。尝试:

emit TypeEditor::valueChanged();

答案 2 :(得分:0)

  

这是一个信号过载的问题。

首先,你的问题是C ++,而不是Qt问题。那么在你的情况下,你不能说超载。

如果在派生类中定义一个与基类方法具有相同名称和签名的方法,那么您将重载。如果你有b-&gt; valueChanged(),这个信号没有在基类中定义参数,这里就没有编译错误。

编译代码时,编译器会查找最近范围内的valueChanged()信号,即B类的范围。他找到了一个valueChanged(bool)然后检查参数列表。由于没有匹配,因此存在编译错误。

答案 3 :(得分:0)

您正在做的事情被称为“遮蔽”或“隐藏”名称。当编译器将继承层次结构复制到基类(我知道还有更多内容,我只是简化)时,它首先查看当前作用域以查看是否存在具有相同名称的内容。如果它可以找到与您要查找的成员具有相同名称(不是签名或类型)的成员,那么即使在继承层次结构中有更好的候选者,它也不会再看了!

那么,你怎么解决这个问题呢?您可以使用using语句将声明从父类导入到派生类中。 (您可以看到有关此here的更多信息。)

例如:

struct A {
    int f() { return 42; }
};

struct B : A {
    using A::f; // <- This is the magic line!
    int f(int n) { return 42 + n; }
};

派生类中的using A::f;语句将f成员从A添加到当前作用域中,现在这两个函数都可见并可以使用!

Here是关于ideone的可运行示例。