8

I'm having a problem with QT regarding multiple enheritance because of QObject. I know that a lot of others have the same problems but I don't know how I should fix it.

class NavigatableItem : public QObject
{
    Q_OBJECT

    signals:
        void deselected();
        void selected();
        void activated();
};

class Button : public NavigatableItem, public QToolButton
{
    Q_OBJECT

    ...
}

class MainMenuOption : public Button
{
    Q_OBJECT

    ...
}

When I do this

MainMenuOption* messages = new MainMenuOption();
connect(messages, SIGNAL(selected()), SLOT(onMenuOptionSelected()))

I will get the error:

QObject' is an ambiguous base of 'MainMenuOption'

The reason why I let NavigatableItem enherit from QObject because of the signals. Is there a way to do this?

Edit:

Adding virtual to each inheritence declaration, still gives me the same error:

class NavigatableItem : public virtual QObject

class Button : public virtual NavigatableItem, public virtual QToolButton

class MainMenuOption : public virtual Button

Even after a 'clean all', 'run qmake' and 'build all'.

Louis Langholtz
  • 2,913
  • 3
  • 17
  • 40
RvdK
  • 19,580
  • 4
  • 64
  • 107

3 Answers3

8

It requires a bit more code, but what I have done in the past is make one of them (your NavigatableItem in this case) a pure virtual class, i.e. interface. Instead of using the "signals" macro, make them pure virtual protected functions. Then multiply-inherit from your QObject-derived class as well as the interface, and implement the methods.

I know it is somewhat controversial, but avoiding multiple implementation inheritance at all costs does solve a host of problems and confusion. The Google C++ Style Guidelines recommend this, and I think it is good advice.

class NavigatableItemInterface
{
    // Don't forget the virtual destructor!
    protected:
        virtual void deselected() = 0;
        virtual void selected() = 0;
        virtual void activated() = 0;
};

class Button : public NavigatableItemInterface, public QToolButton
{
    Q_OBJECT
    ...
    signals:
        virtual void deselected();
        ...
}
Dave Mateer
  • 17,608
  • 15
  • 96
  • 149
  • Thanks Dave, this is what I did meanwhile so I could build the project at least. However one side effect is that if I have a textentry object that needs to be a NavigatableItem, I have to redefine each deselected/selected and activated signals. – RvdK Mar 23 '11 at 13:40
  • 2
    You will have to redefine them, but you should not have to reimplement them. There is usually is a way to put these in some common class (perhaps just a utility class), include this as a private member of your inheriting class, and make your inheriting class have a 'has-a' relationship rather than an 'is-a' relationship. Yes, it is a bit of extra code, but your actual business logic can usually be kept in one place so that you avoid "copy and paste" errors. I've found it is worth it to avoid the other problems with multiple inheritance, but I readily acknowledge that as just an opinion. – Dave Mateer Mar 23 '11 at 15:20
0

Use virtual inheritence, e.g.

class X : public virtual Y 
{
};

class Z : public virtual Y
{
};

class A : public virtual X, public virtual Z
{
};

will only have one copy of the base class Y

mPopp
  • 160
  • 1
  • 4
Chris Card
  • 3,216
  • 20
  • 15
  • I added virtual to all inheritance declaraties but it still gave me the same error. – RvdK Mar 23 '11 at 10:56
  • 1
    Try regenerating the MOC-files by running: make distclean; qmake; make. – Tobias Mar 23 '11 at 11:28
  • See updated question. Adding virtual and rebuilding didn't fix it. – RvdK Mar 23 '11 at 13:38
  • 3
    @PoweRoy: Since you can't make QToolButton inherit QObject virtually, it won't work in this case. – Jan Hudec Mar 23 '11 at 13:54
  • 1
    There should *NOT* be any `virtual` in declaration of `class A`. Only `Y` has to be inherited virtually and that's exactly what PoweRoy *can't* do. – Jan Hudec Mar 23 '11 at 13:56
0

You should use virtual inheritance.

see http://en.allexperts.com/q/C-1040/virtual-inheritance.htm

Seems like you are experiencing the diamond issue, see also:

http://www.cprogramming.com/tutorial/virtual_inheritance.html

Do it like this:

class NavigatableItem : public virtual QObject
class Button : public virtual NavigatableItem, public virtual QToolButton
class MainMenuOption : public Button
Mojtaba Ahmadi
  • 1,044
  • 19
  • 38
snoofkin
  • 8,725
  • 14
  • 49
  • 86