Solving design involving multiple inheritance and composite classes in c++

前端 未结 4 1789
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-09 05:14

I have struggled with this design problem for some time. I will do my best to explain what I am trying to do and the various approached that I have seen, what I am trying and wh

相关标签:
4条回答
  • 2021-02-09 05:50

    Maybe you could change data models to implement something component based. Each component could contain the same state information you mentioned for the different types. And you could inherit virtual functions

    class Galaxy
    {
      // galaxy information
    
      // Virtual functions shared among galaxies
      virtual void sharedGalaxyFunction() = 0;
    
      // Vector containing all solar systems in this galaxy
      std::vector<SolarSystem*> solarSystems_;
    };
    
    class SolarSystem
    {     
      // solar system info
    
      // Virtual functions shared among all solar systems
      virtual void sharedSolarSystemFunction() = 0;
    
      // Vector containing planets
      std::vector<Planets*> planets_;
    };
    
    // etc for planets...
    

    You could then inherit the different types of solar systems or galaxies to create the special cases and fill out the virtual function calls

    class CoolSolarSystem : public SolarSystem
    {
      // Special variables
    
      // Fill in the virtual function
      void sharedSolarSystemFunction();
    };
    

    You could then populate the containers inside the different base types with the pointers to your special types. You should be able to avoid a cast back to the special type if the virtual function calls handle enough of that information.

    0 讨论(0)
  • 2021-02-09 06:06

    So if I understand your question right:

    1. There are several types of galaxies that can have nothing at all in common between them.
    2. The same goes for Solar and planetary systems.
    3. You would like to combine collections of these different types and yet have full access to the underlying methods for that type.

    This sounds like a case for boost::any

    So now your Galaxy is:

    #include <list>
    #include <boost/any.hpp>
    typedef std::vector<boost::any> collection;
    class Galaxy
    {
       collection SolarSystems;
       public:
       ...methods...
    };
    class SolarSystem
    {
       collection PlanetarySystems;
       public:
       ...methods...
    };
    class PlanetarySystem
    {
       collection Moons;
       public:
       ...methods...
    };
    

    Ofcourse, this doesn't really do anything, but does allow you to group them. In order to do anything useful (call a method) you will still have to detect the type, cast it to that type and then run the code you need to.

    However, what this does allow you to do is to group objects of different types together, which I think is what you're after with GalaxyOneTwo. Here is more information on how you can do that.

    0 讨论(0)
  • 2021-02-09 06:08

    I think you have to have one class Galaxy, one class SolarSystem, etc. And yours GalaxyOne, GalaxyTwo SolarSystemOne, SolarSystemTwo etc. are only different objects instantited from these classes.

    class SolarSystem { /* … */ };
    class Planet{ /* … */ };
    class Moon{ /* … */ };
    
    class Galaxy{ /* … */
     public: // Galaxy(...?...){for (...) {read data??; solarSystem.push_back(createSolarSystem(data)); }
     void AddSolarSystem(SolarSystem* ss){solarSystem.push_back(ss);}
     protected:
       std::vector<SolarSystem*> solarSystems;
       /* … */
    };
    

    ....

    Galaxy GalaxyOne, GalaxyTwo;
    

    If we have no way to use this simple aproach... Lets see yours:

    class GalaxyOneTwo: public GalaxyOne, 
                        public GalaxyTwo, 
                        public PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>{
        /* … */
     using PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>::solarSystems;
     GalaxyOneTwo(){solarSystems.reserve(10);}
    };
    

    Here you have three private vectors: (using using you make it direct accesible)

    std::vector<SolarSystemOne*   > GalaxyOne::solarSystems;
    std::vector<SolarSystemTwo*   > GalaxyTwo::solarSystems;
    std::vector<SolarSystemOneTwo*> solarSystems; //GalaxyOneTwo::solarSystems;
    

    Is this what you need? Make it protected? enter image description here

    0 讨论(0)
  • 2021-02-09 06:11

    You need to abstract out the common stuff between the 'One' and 'Two' versions of stuff into a set of 'Common' base classes:

    class GalaxyCommon {
        // all the common stuff between GalaxyOne and GalaxyTwo including
        std::vector<SolarSystemCommon *> solarSystems;
        ...
    };
    
    class GalaxyOne : public virtual GalaxyCommon {
        // all the stuff that is unique to model One
    };
    
    class GalaxyTwo : public virtual GalaxyCommon {
        // all the stuff that is unique to model Two
    };
    
    class GalaxyOneTwo : public virtual GalaxyOne, public virtual GalaxyTwo {
        // should be complete
    };
    

    Note the use of virtual -- required to get properly working multiple inheritance.

    0 讨论(0)
提交回复
热议问题