3

When I try to connect a BASE class signal, Qt tells me the signal does not exists on the DERIVED class.

Why is that? How can I tell connect to use the BASE class?

namespace MyNamespace 
{

void register(Derived* derived)
{
    // ERROR MSG
    // QObject::connect: No such signal MyNamespace::Derived::baseSignal()

    QObject::connect( derived, SIGNAL(baseSignal()), 
                      foo,     SLOT(fooSlot())); 
}

class Base : public QObject
{
    Q_OBJECT

signals:
    void baseSignal();
};

class Derived : public QObject,
                public Base
{
    Q_OBJECT

signals:
    void derivedSignal();
};

} // namespace MyNamespace
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
Octo
  • 543
  • 1
  • 5
  • 16
  • 1
    If I cast the sender as Base * in connect() I get the same error. – Octo Jul 16 '15 at 20:58
  • Derived contains derivedSignal(), not baseSignal(). You are telling Qt to connect to baseSignal() but passing a Derived as the object where it should look for that function. What happens if you pass a Base * to register()? – underscore_d Jul 16 '15 at 20:58
  • I tried to compile it. There was a warning message which tells me that Derive should not inherited from `QObject`, because base is already inherited from that. – p.i.g. Jul 16 '15 at 21:02
  • If I cast the sender as Base * in connect() I get the same error. – Octo Jul 16 '15 at 21:03
  • 1
    And register is a keyword, so you should find another word. – p.i.g. Jul 16 '15 at 21:03
  • Why are you repeating yourself? I asked what happens if you passed a Base * to register(), not connect() – underscore_d Jul 16 '15 at 21:04
  • @underscore same error – Octo Jul 16 '15 at 21:10
  • @p.i.g this is just an example. Not the real name of the function. – Octo Jul 16 '15 at 21:11

2 Answers2

5

Your problem is that you're multiply deriving Derived from QObject: you derive from it directly and through the Base class. Don't do that, since Qt doesn't support multiple derivation from QObject, not even virtual derivation.

The second and subsequent QObject bases are ignored by the QObject system. Thus, to the QObject machinery, the Derived class only derives from QObject, and not from Base - thus it doesn't know about baseSignal. As they well should be, since the support of multiple QObject derivation would incur runtime overheads - and in any case, you'd need to virtually inherit QObject, and you didn't even do that!

At the very minimum, if you expected such to work, your code would need to look as follows:

class Base : public virtual QObject { ... };
class Derived : public Base, public QObject { ... };

... but Qt doesn't support that.

You'd have been luckier if you wrote the Derived class to inherit the base class first:

class Base : public QObject { ... };
class Derived : public Base, public QObject { ... };

This would have worked, although the second QObject base would be pointless and ignored by the QObject machinery.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
1

It would be much better in this form:

namespace MyNamespace 
{

class Base : public QObject
{
    Q_OBJECT

signals:
    void baseSignal();
};

class Derived : public Base
{
    Q_OBJECT

signals:
    void derivedSignal();
};

void registerX( Derived* derived )
{
    QObject::connect( derived, SIGNAL(baseSignal()), foo, SLOT(fooSlot()));
}

} // namespace MyNamespace

As this post says you shall not inherit QObject multiple times.

Community
  • 1
  • 1
p.i.g.
  • 2,815
  • 2
  • 24
  • 41