我创建了一个基类,为其所有子类提供公共信号:
#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()
的函数。
当我将基类中的信号重命名为其他可用的信号时,这似乎是信号过载的问题。我会对此感兴趣。是否有一些我不知道的设计要求会阻止我在子类中重载信号,或者我只是遗漏了代码中的某些内容?
答案 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的可运行示例。