• Create Account

### #ActualGeometrian

Posted 22 January 2013 - 12:41 AM

Does AppChild2 contain two instances of LibBase, or just one? I would think that you just want one instance of LibBase to do multiple inheritance correctly. I can't remember how the two super classes would share one instance of that base class, unfortunately. Does ordering the construction of the base classes in the AppChild2 constructor have any effect? Remember to use the access specifier for these base classes in your constructor, because if you just rely on them instantiating themselves using their no-arg constructors in the constructor body, I think that the order is not guaranteed (again, can't recall if this is the case).

Yes, there should be exactly one instance of "LibBase" for each instance of "AppChild1" and "AppChild2". All the classes have nontrivial constructors--in fact, that's one of the key reasons I need "LibChild" at all.

My understanding is that the general way you solve the diamond inheritance problem is with virtual inheritance, i.e.:

class LibBase {...};

class LibChild : public virtual LibBase {...};

class AppBase : public virtual LibBase {...};

class AppChild1 : public AppBase {...};

class AppChild2 : public AppBase, public LibChild {...};

This ensures that there is one instance of "LibBase" for each child instance. However, this particular solution is not possible since "LibChild" was defined without virtual inheritance and cannot be changed.

It sounds like generally there's not a quick fix, so, as was rightly suggested, it helps to go back to what we're originally designing.

This code is in the context of maintenance (rewrite in disguise) of an abstraction layer for wxWidgets frames. There are two classes "Frame" and "FrameMini", which encapsulate two kinds of frames. Since they share functionality, but differ significantly, they both derive from a class "FrameBase". The designers wanted to abstract the actual functionality, so they created a backing class to handle the wx backend (which I called "AppBase"). However, the way you construct one kind of frame ("wxFrame", i.e. "LibBase") is different from how you construct another ("wxMiniFrame", i.e. "LibChild"). So, two subclasses were born: "AppChild1" and "AppChild2". The inheritance is as follows (classes renamed):

wxFrame
|
______|_____
|            |
FrameBase               |            |
|                   v            v
____|____            Backing    wxMiniFrame
|         |              |            |
|         |        ______|__________  |
v         v       |                 | |
Frame   FrameMini   |                 | |
v                 v v
BackingFrame     BackingFrameMini

In the above:

• On construction, instances of "Frame" create a new instance of "BackingFrame" and pass it to their parent instance of "FrameBase".
• On construction, instances of "FrameMini" create a new instance of "BackingFrameMini" and pass it to their parent instance of "FrameBase".
• "FrameBase" stores these in a pointer of type "Backing".

The above suggests a new design, where the "Frame" and "FrameMini" classes simply instantiate "wxFrame" or "wxMiniFrame" directly. I don't see any immediate problems with this, and it's simpler, which is only good. Thanks for bouncing ideas.

### #2Geometrian

Posted 22 January 2013 - 12:21 AM

Does AppChild2 contain two instances of LibBase, or just one? I would think that you just want one instance of LibBase to do multiple inheritance correctly. I can't remember how the two super classes would share one instance of that base class, unfortunately. Does ordering the construction of the base classes in the AppChild2 constructor have any effect? Remember to use the access specifier for these base classes in your constructor, because if you just rely on them instantiating themselves using their no-arg constructors in the constructor body, I think that the order is not guaranteed (again, can't recall if this is the case).

Yes, there should be exactly one instance of "LibBase" for each instance of "AppChild1" and "AppChild2". All the classes have nontrivial constructors--in fact, that's one of the key reasons I need "LibChild" at all.

My understanding is that the general way you solve the diamond inheritance problem is with virtual inheritance, i.e.:

class LibBase {...};

class LibChild : public virtual LibBase {...};

class AppBase : public virtual LibBase {...};

class AppChild1 : public AppBase {...};

class AppChild2 : public AppBase, public LibChild {...};

This ensures that there is one instance of "LibBase" for each child instance. However, this particular solution is not possible since "LibChild" is defined without virtual inheritance.

### #1Geometrian

Posted 22 January 2013 - 12:18 AM

Does AppChild2 contain two instances of LibBase, or just one? I would think that you just want one instance of LibBase to do multiple inheritance correctly. I can't remember how the two super classes would share one instance of that base class, unfortunately. Does ordering the construction of the base classes in the AppChild2 constructor have any effect? Remember to use the access specifier for these base classes in your constructor, because if you just rely on them instantiating themselves using their no-arg constructors in the constructor body, I think that the order is not guaranteed (again, can't recall if this is the case). In other words:

AppChild2::AppChild2() :
LibChild(),
AppBase()
{
// constructor body here
}

Yes, there should be exactly one instance of "LibBase" for each instance of "AppChild1" and "AppChild2".

My understanding is that the general way you solve the diamond inheritance problem is with virtual inheritance, i.e.:
class LibBase {...};

class LibChild : public virtual LibBase {...};

class AppBase : public virtual LibBase {...};

class AppChild1 : public AppBase {...};

class AppChild2 : public AppBase, public LibChild {...};
This ensures that there is one instance of "LibBase" for each child instance. However, this particular solution is not possible since "LibChild" is defined without virtual inheritance.

PARTNERS