3

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

#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

4 回答 4

3

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

有关更多详细信息,请参阅此问题

于 2013-05-17T08:56:01.243 回答
2

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

emit TypeEditor::valueChanged();
于 2013-05-17T08:56:24.943 回答
0

这是信号过载的问题。

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

如果您在派生类中定义与基类方法具有相同名称和签名的方法,那么您正在重载。如果你有 b->valueChanged(),这个信号没有在基类中定义参数,你不会得到编译错误。

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

于 2013-05-18T07:07:54.287 回答
0

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

那么,你如何解决这个问题?您可以使用语句将声明从父类导入派生类using(您可以在此处查看更多相关信息。)

例如:

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成员 from添加A到当前范围中,现在这两个函数都是可见的并且可以使用!

是 ideone 上的一个可运行示例。

于 2018-04-03T19:37:34.520 回答