You are not logged in.

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

1

Thursday, August 4th 2005, 10:27pm

Multiple Inheritance and QObject

I am currently trying to build a set of custom widgets that add additional functionality to the standard QWidget. Each widget has its own set of functions which are different from the rest, and they also have a set of functions that be will the same across all of the custom widgets. This problem is crying out "Use multiple inheritance." Using multiple inheritance will allow me to create a base class, that all of my custom widgets can inherit, which would add the additional functions that are the same throughout all the widgets, without having to write the same code over and over. This setup was working great until I needed to use Signals and Slots in my base class. To do this, the bass class must inherit QObject, and since QObjects are not inherited virtually, this cannot be done.

This seems like a huge limitation to Qt because the end result is, I have to code the signals and slots functions, multiple times, across all the custom widgets. Regardless of the fact that the code is generic, and identical. Seems to me, if the QObjects are to be setup so that you cannot use mutliple inheritance of qobject, then the singals and slots should not be dependent of qobjects. This way you can use signals and slots in other classes.

The reason for this post is not to bash Qt (since this is by far my favorite developing tool yet), but rather a question as to how can I get around this limitation. Or am I simply not seeing the big picture. My problem though is a valid one. How can I turn classes into peices of a larger whole, adding functionality to a parent class much like adding another module to your kernel, and still be able to use signals and slots.

2

Thursday, August 4th 2005, 11:15pm

RE: Multiple Inheritance and QObject

The problem is complicated, I'm not sure I understand completely without some form of object/inheritance diagram, but have you used the alternate syntax form:
class MyClass : public virtual QObject
{
...
};

I don't know if this would work at all for your situation, if not maybe you could show some sort of inheritance diagram (just plain text).
-- "Quality is free", quoted from Dr. W. E. Deming

chickenblood

Professional

Posts: 657

Location: Mountain View, CA

Occupation: Data Monkey

  • Send private message

3

Friday, August 5th 2005, 7:13am

RE: Multiple Inheritance and QObject

You can try downloading the boost::signals library to get a QObject-free implementation of signals and slots.

http://boost.org/doc/html/signals.html

Be warned though, it's not as 'pleasant' to use.
I have enough sense to know that "common sense" is an oxymoron.

  • "wysota" is male

Posts: 4,276

Location: Warsaw, POLAND

  • Send private message

4

Friday, August 5th 2005, 7:53am

RE: Multiple Inheritance and QObject

Can't you do:

class Common : public QWidget;

class Individual1 : public Common;
class Individual2 : public Common;

etc.?

In Common you implement things which your custom widgets share, and then derive from the class to implement specific parts.

5

Friday, August 5th 2005, 12:58pm

Unfortianitly I can't go into huge details about what I am doing (Government stuff), but here is an idea of what I have

Core product object starts with,

class CoreWidget1: public QWidget
{}

class Core Widget2: public QWidget
{}

I can't change CoreWidgets 1 and 2, but I can inherit them, and add things I need for my project. So I have

class Common: public QObject //for signals and slots

class myWidget1: public CoreWidget1, public Common
{}

class myWidget2: public CoreWidget2, public Common
{}

Like I said this worked great until I made Common a derivative of QObject to be able to use signals and slots.

The virtual idea is what should be done, but won't work because QObject wasn't a vitual class to begin with.

One thing I noticed is that if I add singals, and slots to my class, without it Inheriting QObject, the compiler does complain. I would imagine that the singals and slots simply won't work if you used Common as you base class. However, and this is what I want to see, is if the signals and slots start to work if I inherit Common, and a class that is derived from QObject.

As for the boost link, it doesn't work..

Thanks guys...... I will let you know what I find, if you have more suggestions, keep them coming.

Posts: 2,162

Location: Graz, Austria

Occupation: Student

  • Send private message

6

Friday, August 5th 2005, 1:22pm

You could just use aggrregation instead of inheritance

For example

Source code

1
2
3
4
5
6
7
8
class MyWidget : public CoreWidget
{
public:
    Common* common() { return m_common; }

private:
    Common* m_common;
};


Or the other way around, i.e. creating a Common subclass and allowing access to the associated widget.

Qt3's QCanvas works this way.

Cheers,
_
Qt/KDE Developer
Debian User

jacek

Master

  • "jacek" is male

Posts: 2,729

Location: Warsaw, Poland

  • Send private message

7

Friday, August 5th 2005, 1:36pm

Maybe templates will help?

Source code

1
2
class myWidget1: public Common<CoreWidget1>;
class myWidget2: public Common<CoreWidget2>;
But unfortunately you won't be able to cast all of those custom widgets to Common. You could add another class, say CommonBase, and derive Common class template from it. This way you can have both signals & slots and a common interface.

Another solution is to change the Qt sources and make QWidget use virtual inheritance.

Anyway, IMO the best workaround so far is to use aggregation, as anda_skoa proposed.

8

Friday, August 5th 2005, 2:13pm

If I change Qt's classes to be virtual, how will that effect the overall functionaility though. I mean, this Qt stuff is pretty slick. I would imagine that the Qt developers didn't make the classes virtual for a reason.

jacek

Master

  • "jacek" is male

Posts: 2,729

Location: Warsaw, Poland

  • Send private message

9

Friday, August 5th 2005, 2:26pm

Quoted

Originally posted by rpquinn
I would imagine that the Qt developers didn't make the classes virtual for a reason.

Qt alone should work, but QObject might not be capable of handling multiple inheritance. For example QObject::inherits() and QObject::isA() methods might cause troubles.

It will probably take more time to make this work than using one of the workarounds.

chickenblood

Professional

Posts: 657

Location: Mountain View, CA

Occupation: Data Monkey

  • Send private message

10

Friday, August 5th 2005, 3:47pm

Quoted

Originally posted by wysota
Can't you do:

class Common : public QWidget;

class Individual1 : public Common;
class Individual2 : public Common;

etc.?

In Common you implement things which your custom widgets share, and then derive from the class to implement specific parts.


I thought of this, but the problem is, that if you wanted Individual1 to be a QLineEdit widget and Individual2 to be a QLabel widget (for example), then they must inherit from those classes and not Common. In this case the solution is not easy to find somewhere to implement the common behaviour that you require.
I have enough sense to know that "common sense" is an oxymoron.

This post has been edited 2 times, last edit by "chickenblood" (Aug 5th 2005, 4:04pm)


chickenblood

Professional

Posts: 657

Location: Mountain View, CA

Occupation: Data Monkey

  • Send private message

11

Friday, August 5th 2005, 3:56pm

RE: Multiple Inheritance and QObject

Quoted


As for the boost link, it doesn't work.


Sorry, I'll try again: http://www.boost.org/doc/html/signals.html
I have enough sense to know that "common sense" is an oxymoron.

This post has been edited 2 times, last edit by "chickenblood" (Aug 5th 2005, 4:03pm)


12

Friday, August 5th 2005, 4:03pm

If you do this it works fine (except when common is a QObject... which is the reason for this thread)

class Common

class myWidget1: public QLineEdit, public Common
class myWidget2: public QLabel, public Common

So far I am still trying to create an environment where I can test your above suggestions.

chickenblood

Professional

Posts: 657

Location: Mountain View, CA

Occupation: Data Monkey

  • Send private message

13

Friday, August 5th 2005, 4:05pm

Quoted

Originally posted by rpquinn
If you do this it works fine (except when common is a QObject... which is the reason for this thread)


Yes, you can't have signals and slots in Common. We understand.
I have enough sense to know that "common sense" is an oxymoron.

14

Friday, August 5th 2005, 8:18pm

Here's what Stroustrup says:
"Every virtual base of a derived class is represented by the same (shared) object."
Then he goes on to make examples of multiple inheritance without any virtual methods involved in a similar situation.

But at first glance this seems like it won't do you any good, because you said:
class CoreWidget1: public QWidget
class Core Widget2: public QWidget
... and you can't modify those to be virtual public instead of just public QWidget.

On the other hand you did say that the signal and slot class was yours, as well as things inheriting it:
class myWidget1: public CoreWidget1, public Common

So, if the signal and slot part is the problem, why not:
class Common: virtual public QObject
class myWidget1: public CoreWidget1, virtual public Common

Note the added virtual key word to public Common. All of your signals and slots would use the same base class.

One possible problem is that each QWidget *is* a QObject, and each QObject has its own signal/slot mechanism. If you make sure that the only signal slot mechanism used is from your Common class it should work. If there is some form of conflict with signals and slots using the CoreWidget signal/slot mechanism, you can make accessor signals and slots in the Common class that simply relay the same signal and slot using a different name...then you use the different name and only the Common version will get called or sent.
-- "Quality is free", quoted from Dr. W. E. Deming

15

Monday, August 8th 2005, 12:58pm

Good call VirtualBrainSucker! So far all of my testing has shown that your previous idea works. I will get back with further detail later,

Thanks

16

Monday, August 8th 2005, 3:46pm

Well the final result is that this can not be done. The above ideas are all great except that the Common class cannot call a signal unless it is in the Common class. So what really is going on here is a poor design. It would be nice to be able to creat pieces to a puzzle, and then when a class wants that piece, I simply inherit that piece and "PUFF", it works. But this has proven to be a limitation of C++, not Qt. See, even if Qt had virtual QObject classes, I would still have to capture the event that causes the signal to be emited. This event is part of a QWidget. And if I overload the event in the Common class, I now have two instances of this event. There for the class inheriting these two classes needs to resolve this ambiguity. Therfore, work has to be done to allow these two pieces to be inherited together. Thereby killing my hopes of simply add the extra class and be done. It has also proven easier to simply add the functionality I wanted to the CoreWidget class manually. Even though this is against the idea of not writing the same code more than once, C++ realy didn't give me a choice here. Thank you for all your help, sorry to someone else who ran into a similar problem, however I would re-think your design approach and ask, is what I want to do really going to help! It didn't in my case. Great forum response though!!! Really impressed. Thanks guys

Rian

chickenblood

Professional

Posts: 657

Location: Mountain View, CA

Occupation: Data Monkey

  • Send private message

17

Monday, August 8th 2005, 5:27pm

I'm still not sure why you could not achieve this easily with boost::signals, since they are totally self-contained and do not rely on QObject inheritance.

I'm not a huge proponent of boost (never used it in production code), but it seems that a case like this one would be a great candidate to utilize/test the power that it offers.
I have enough sense to know that "common sense" is an oxymoron.

18

Monday, August 8th 2005, 6:02pm

This major issue is more than just signals and slots. The signal being produce is emitted from a closeEvent () function which is QWidget function. If I use signals and slots, the signal has to emited from class that signal. For this idea to work, I would have to be able to emit the signal from another class that defines the signal. This is the major reason why I believe my deisng is flaued.

chickenblood

Professional

Posts: 657

Location: Mountain View, CA

Occupation: Data Monkey

  • Send private message

19

Monday, August 8th 2005, 6:32pm

I believe that a multiple inheritence design is inherently flawed (usually) and the use of interfaces or mix-in classes (as advocated in Java) is usually a much better approach.

I'm still convinced that what you have in mind is implementable though. I'm happy to drop the issue (since it's your thread), but if you change your mind I'd be willing to sketch out a skeleton design using Qt and boost::signals.

Just for fun.

Cheers,
Ian
I have enough sense to know that "common sense" is an oxymoron.

20

Monday, August 8th 2005, 6:40pm

Absolutely... If you think it can be done. It minimum this would help to better educate anyone else who might read this thread, as well as help to clean up my code :).