toster
toster

Reputation: 332

Qt: inherited signal not recognized in subclass

I have created a base class that provides a common signal for all its subclasses:

#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

In a subclass, I want to have this signal available, but also define a more specific signal with the same name but different arguments:

#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

The idea is that when only the base class type is known, the generalized signal can be used, which tells that there has been a change in the value. When the exact subclass type is known, another signal is available, which tells the new value.

Now, when I try to compile I get an error on the emit valueChanged() stating that there is no function called Dino::BoolEditor::valueChanged().

When I rename the signal in the base class to something else it works, so this seems to be a problem of overloading the signal. I would be interested in the reason for this. Is it some design requirement that I'm not aware of that prevents me from overloading a signal in a subclass, or am I just missing something in the code?

Upvotes: 3

Views: 6817

Answers (4)

callyalater
callyalater

Reputation: 3102

What you are doing is called "shadowing" or "hiding" a name. When the compiler does its magic to copy an inheritance hierarchy into a base class (I know that there is more to that, I'm just simplifying), it first looks in the current scope to see if there is something with the same name. If it can find a member with the same name (not the signature or type) as what you are looking for, it doesn't look any further, even if there are better candidates in the inheritance hierarchy!

So, how do you get around this? You can import the declaration from the parent class into the derived class with a using statement. (You can see more about this here.)

For example:

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

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

That using A::f; statement in the derived class adds the f member from A into the current scope and now both functions are visible and can be used!

Here is a runnable example on ideone.

Upvotes: 0

kiriloff
kiriloff

Reputation: 26333

it is a problem of overloading the signal.

First, your issue is a C++one, not a Qt one. Then in your case,you cannot speak of overloading.

If you define in derived class a method with same name and signature than a base class method,then you are overloading. If you had b->valueChanged(), with this signal with no parameters defined in base class, here you would get no compile error.

When compiling your code, compiler looks fot a valueChanged() signal in closest scope, that is scope of B class. He finds a valueChanged(bool) and then checks argument list. Since there is no match, there is compile error.

Upvotes: 0

Amartel
Amartel

Reputation: 4286

This is overloading methods in C++. Try:

emit TypeEditor::valueChanged();

Upvotes: 2

spiritwolfform
spiritwolfform

Reputation: 2293

Signal is just a protected function. You can't overload base class functions like that

See this question for more details

Upvotes: 4

Related Questions