Extending two class "the same way"
I have a class hierarchy that contains amongst others
Code:
class Dialog { ... };
class SpecialDialog : public Dialog { ... };
I also have a class
Code:
class ListDialog : public Dialog { ... };
The functionality of "ListDialog" does not depend on the extensions of SpecialDialog, it would have been possible to have it extend SpecialDialog as well.
And that is just my question:
Going from the (already implemented) above classes, is there an easy way to have both a ListDialog and a "SpecialListDialog" that is identical but inherits SpecialDialog instead. (Ideally the solution should allow even further "Dialog"-based classes as subclasses.
I would hate to copy the source and just change the few references to the base class (mostly in virtual methods). I also don't like too many implementation details in headers (otherwise I'd make a template)...
I am aware that I could put the complete implementation into the header and make the class a template and the base class a template parameter. (I am looking for a different solution, if possible.)
Another idea would be to try to put the extension of ListDialog into a separate class and use multiple inheritance. But how would you override the virtual functions, then? (Yes, Dialog does contain virtual methods which are overridden in ListDialog..)
Best regards and thank you for your ideas.
(A similar problem is when you want to extend two different (existing) Qt widgets by common functionality...)
Re: Extending two class "the same way"
To me it seems what you want is more composition than generalization. Basically what you can do is to design interfaces describing each of the "additions" to the Dialog class and then make the "subclasses" implement them. This doesn't have to be through inheritance, the most trivial solution would be to use aforementioned composition.
Code:
class A {
public:
virtual void x() = 0;
};
class B {
public:
virtual void y() = 0;
};
class C {
public:
const A* a() const { return &m_AImpl; }
const B* b() const { return &m_BImpl; }
private:
AImpl m_AImpl; // where AImpl inherits A
BImpl m_BImpl; // where BImpl inherits B
};
This is more or less what is done in Qt Creator and is called aggregation there.
What Creator uses is a kind of dynamic aggregations where you can add objects to the "mother-object" on demand. Unfortunately I can't find any articles about such a feature right now. In general you can query an object for an interface and if it has sub-object implementing it, they will be returned.
Re: Extending two class "the same way"
Thank you, I will think about that.
The only annoying thing is that this are not "pure" additions, but the ListDialog does reimplement several virtual methods. It is not obvous how to best deal with several such additions as in your example that all might reimplement a, say, keyHandler() to handle some keys...
Re: Extending two class "the same way"
Quote:
Originally Posted by
caduel
The only annoying thing is that this are not "pure" additions, but the ListDialog does reimplement several virtual methods.
Those virtual methods may be an object in the base class as well.
Quote:
It is not obvous how to best deal with several such additions as in your example that all might reimplement a, say, keyHandler() to handle some keys...
Very easy. The base class asks the current object if it implements this particular interface and if so, it delegates the call to it.
Code:
class Base {
public:
virtual void keyHandler(int x){
// the method doesn't even need to be virtual (which maintains binary compatibility by the way)
KeyHandlerIface *kh = objectFor<KeyHandlerIface*>(this); // ask "this" aggregate to return "KeyHandlerIface" object
if(kh){
kh->handleKey(x);
} else {
//...
}
}
};
Of course you need to build upon this, objectFor() needs to be implemented using templates and/or qobject_cast.