I struggled with this design problem for a while. I will do my best to explain what I'm trying to do, and the different approaches that I saw, what I'm trying and why.
I work in a scientific computing environment where I repeatedly come across the same types of objects. Imagine a galaxy that contains solar systems, every solar system contains planetary systems, and every planetary system contains moons. To this end, I consider the situation a βsituationβ, and therefore I used composition to give the galaxy access to its solar systems, and each solar system gets access to planetary systems that have access to their moons: each category being its own class.
It often happens that the various problems I'm working on contain different types of data about these objects. And, when different types of data are available, I can do certain things with my objects. So, when I have data type 1 available to me, I create the following classes
class GalaxyOne { }; class SolarSystemOne { }; class PlanetOne{ }; class MoonOne{ };
And when I have data type 2 available to me, I create
class GalaxyTwo { }; class SolarSystemTwo { }; class PlanetTwo{ }; class MoonTwo{ };
The complex aspects of each class are considered using container variables, such as vectors that contain pointers to the contained classes. For example, in every class of the Galaxy one could find.
class GalaxyTwo{ protected: std::vector<SolarSystemTwo*> solarSystems; };
The difficulty arises when I want to combine classes into classes of a higher order.
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo{ };
However, this creates an ambiguity problem in the solarSystems vector, because GalaxyOneTwo will have a version from GalaxyOne and GalaxyTwo. In addition, inherited vectors contain pointers to objects that are not of the type of SolarSystemOneTwo that is required. So, I thought I could create a template class that inherits all my objects, from where I put all my container variables.
template<MoonT,PlanetT,SolarSystemT> class PrimitiveGalaxy { private: std::vector<SolarSystemT*> solarSystems }; class GalaxyOne: public PrimitiveGalaxy <MoonOne,PlanetOne,SolarSystemOne>{ };
This approach is very well suited for those fundamental types of Galaxy (GalaxyOne and GalaxyTwo). However, whenever I try to create a combined type of galaxy, I get all kinds of ambiguities.
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo, public PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>{ };
I get ambiguity if I use solarSystems in any method defined in GalaxyOneTwo because it is defined three times, once through each legacy version from GalaxyOne and GalaxyTwo, and the third time through GalaxyOneTwo.
I can get rid of this ambiguity by being specific and using
PrimitiveGalaxy :: SolarSystems
each time refer to its own vector, but this is undesirable because it requires a lot of extra input and syntax.
I have considered using friendships between each type of galaxy and a primitive galaxy, but this requires a similar level of detailed writing.
I have a suspicion that namespaces may simplify my code entry, but I'm not sure how to define a namespace in such a way that in the namespace defined for GalaxyOneTwo that any reference to solarSystems is a reference to PrimitiveGalaxy :: SolarSystems
Edit:
Please note that the only difference between GalaxyOne and GalaxyTwo is NOT the type of the class contained in solarSystems. There are many differences because each class deals with different data related to the galaxy. Thus, I create different classes that will have different state variables, getters and setters for these state variables and methods for calculating and printing data. solarSystems is an example of a function that gives me problems, so this is what I described here. When GalaxyOneTwo is created, it will use the same data that is used for GalaxyOne and GalaxyTwo, and therefore I want to inherit all their variables and methods. And since data can be combined in different ways, I need to create new methods for this in GalaxyOneTwo. These are some of the many differences that make me use inheritance. That being said, these are container variables that allow me to create compositions that give me problems. Within each SolarSystem class, a similar vector will exist, giving them access to their planets, etc. Etc.
Edit:
For a question specifically dedicated to my design philosophy here in general (as opposed to those questions about trying to solve my current design attempt), see the following link: Design Guide for Composite Classes with Multiple Inheritance in C ++