我打算将这个问题作为一个更广泛的问题,与我在以下链接中找到的问题有关:
Solving design involving multiple inheritance and composite classes in c++
我正在处理与Galaxies相关的数据集。有关每个星系的数据将包含有关星系太阳系,每个太阳系行星和每个行星卫星的信息。
综合要求:
仅凭这一点,我想我需要使用复合类设计,为星系,太阳系,行星和卫星创建一个类。 galaxy类将包含成员容器变量,其中包含指向太阳系,行星和卫星的指针以及适用于这些容器变量的成员getter和setter函数。太阳系有一个类似设计的成员容器变量,其中包含指向所包含的行星和卫星的指针以及吸气剂和固定器,以及行星等等。
多重继承要求:
我用于每个类的输入数据类型不是常量。有时我有类型1的数据,有时可能是类型2的数据。我对任何给定项目的不同类型的数据可能会随着时间的推移而改变。为了避免拥有一个怪异增长的星系类,它为每个项目提供新的成员变量和函数,以及所有旧项目(当前项目中可能未使用的),我想打破星系,solarSystem ,行星和月亮分为相关的类,每个类专门处理一组特定的数据。
因此,如果我考虑两个可能的数据集,data1和data2,我可以选择为每个数据集创建每个类的特定版本。
我喜欢这种方法,因为如果我有一个需要data1和data2组合的新项目,我可以为galaxy,solarySystem,planet和moon类创建新类,这些类继承之前的两个相关类型。如下所示。
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo { /* . . . */ };
class SolarSystemOneTwo: public SolarSystemTwo, public SolarSystemOne{ /* . . . */};
class PlanetOneTwo: public PlanetTwo, public PlanetOne{ /* . . . */ };
class MoonOneTwo: public MoonTwo, public MoonOne{ /* . . . .*/};
这使我可以访问处理data1和data2的所有变量和方法。然后,我可以进一步定义变量和方法,以处理由data1和data2组合产生的新属性。
问题:
这些设计理念,复合要求和多重继承要求中的每一个对我来说都很有效。但是,我真的想同时使用两者。使用两者的困难在于GalaxyOne中允许访问SolarSystemOne指针的容器变量对GalaxyOneTwo没用,因为SolarSystemOne中的指针类型无法访问SolarSystemOneTwo的成员函数。
可能的解决方案:
模板基类 - 创建一个模板基类PrimitiveGalaxy,PrimitiveSolarSystem,PrimitivePlanet,PrimitiveMoon,它包含所有其他类继承的所有容器变量和相关的getter和setter。这是我在上面发布的链接中使用的方法,可以在那里找到它的问题。
虚拟基类 - 有人建议我创建一个基类,它包含所有类型的星系,太阳系,行星和卫星的所有共享功能。这将包括相关指针的容器变量以及它们的getter和setter。通过这样做,指针可以用于指向每种类型的基类,只要基类型包含所有必要的后续定义函数的虚函数,那么我可以避免将指针投射到更复杂的类型。
我对这种方法的关注是,它不仅需要在派生类中为每个新函数在基类中编写虚函数,而且还要求每个派生类都不会在基类中定义每个虚函数。
到目前为止,上述可能的解决方案是我目前唯一能够发布的解决方案。
我想要一个允许灵活代码的解决方案,该代码不需要复杂的语法,并且不需要每个不断增长且难以管理的一系列非常大的类定义。我的项目经常包含新类型的数据,因此我希望能够轻松地为这些新数据创建新的解析器,并且能够使用Galaxy,SolarSystem,Planet和Moon类将数据包含到我的各种项目中。
答案 0 :(得分:1)
我能够通过使用抽象基类来解决我的问题。抽象基类包含我的所有容器变量和适当的getter和setter变量。此外,抽象基类为将在任何派生类中使用的所有方法定义抽象方法。这些方法由预处理程序指令包围,如果还包含定义所述函数的相应头文件,则只包含那些虚函数,这样可以防止进一步的抽象类。
class Galaxy{
protected:
std::vector<SolarSystem*> solarSystems;
public:
void addSolarSystem(SolarSystem*);
#ifdef GALAXYONE
virtual void aGalaxyOneMethod()=0;
#endif
#ifdef GALAXYTWO
virtual void aGalaxyTwoMethod()=0;
#endif
#ifdef GALAXYONETWO
virtual void aGalaxyOneTwoMethod()=0;
#endif
enter code here
};
GalaxyOne.h
#define GALAXYONE
class GalaxyOne{
protected:
/*Private Variables for GalaxyOne*/
public:
void aGalaxyOneMethod(); //No longer abstract
};
GalaxyTwo.h
#define GALAXYTWO
class GalaxyTWO{
protected:
/*Private Variables for GalaxyTwo*/
public:
void aGalaxyTwoMethod(); //No longer abstract
};
GalaxyOneTwo.h
#define GALAXYONE
#define GALAXYTWO
#define GALAXYONETWO
class GalaxyOneTwo: virtual public GalaxyOne, virtual public GalaxyTwo{
protected:
/*Private Variables for GalaxyOneTwo*/
public:
void aGalaxyOneTwoMethod(); //No longer abstract
};
此方案允许用户创建GalaxyOneTwo类型的对象并将其存储在Galaxy指针中,并且仍然可以访问相应的函数。类似的策略与SolarSystems,Planets and Moons一起使用