在c ++中解决涉及多重继承和复合类的设计
我一直在努力解决这个设计问题。 我会尽我所能解释我正在尝试做什么以及我所看到的各种方法,我正在尝试的以及为什么。
我在科学计算环境中工作,在那里我反复处理相同类型的对象。 设想一个包含太阳系的星系,每个太阳系包含行星系统,每个行星系统包含卫星。 为此,我认为这种情况是一种“有”的情况,因此我用组合物使银河进入了它的太阳系,并且每个太阳系进入到可以进入它们卫星的行星系统:每一类作为自己的班级。
通常情况下,我正在处理的各种问题包含有关这些对象的不同类型的数据。 而且,随着不同类型的数据可用,我可以用我的对象做某些事情。 所以,当我有数据类型1可用时,我创建了以下类
class GalaxyOne { /* … */ };
class SolarSystemOne { /* … */ };
class PlanetOne{ /* … */ };
class MoonOne{ /* … */ };
当我有数据类型2可用时,我创建
class GalaxyTwo { /* … */ };
class SolarSystemTwo { /* … */ };
class PlanetTwo{ /* … */ };
class MoonTwo{ /* … */ };
每个类的复合方面通过使用容器变量处理,例如包含指向所包含类的向量。 例如,在每个Galaxy类中都可以找到。
class GalaxyTwo{ /* … */
protected:
std::vector<SolarSystemTwo*> solarSystems;
/* … */
};
当我想将类组合到更高阶的类中时,就会遇到困难。
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo{
/* Additional methods */
};
然而,这造成了太阳系向量模糊的问题,因为GalaxyOneTwo会从GalaxyOne和GalaxyTwo中获得它的一个版本。 此外,它所继承的向量包含指向不属于SolarSystemOneTwo类型的对象的指针,这将是必需的。 所以,我认为我可以创建一个模板类,其中所有对象都从我放置所有容器变量的位置继承。
template<MoonT,PlanetT,SolarSystemT>
class PrimitiveGalaxy {
private:
std::vector<SolarSystemT*> solarSystems
};
class GalaxyOne: public PrimitiveGalaxy <MoonOne,PlanetOne,SolarSystemOne>{
/* No longer defining any container variables for composition */
};
这种方法对于那些基本的Galaxy类型(GalaxyOne和GalaxyTwo)非常适用。 但是,每当我尝试创建组合星系类型时,我都会遇到各种模糊问题。
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo, public PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>{
/* … */
};
如果我在GalaxyOneTwo中定义的任何方法中使用solarSystems,我会得到歧义,因为它定义了三次,一次是通过GalaxyOne和GalaxyTwo的每个继承版本,另一次是通过GalaxyOneTwo定义的。
我可以通过具体和使用来消除这种歧义
PrimitiveGalaxy :: solarSystems
每次都要引用正确的向量,但这不是所希望的,因为它需要大量额外的输入和语法。
我曾考虑过在每个星系类型和原始星系之间使用友谊,但这需要类似的详细写作水平。
我有一个预感,命名空间可以简化我的代码编写,但我不知道如何定义名称空间,以便在为GalaxyOneTwo定义的名称空间内,任何对solarSystems的引用都是对PrimitiveGalaxy :: solarSystems
编辑:
请注意,GalaxyOne和GalaxyTwo之间的唯一区别不在于太阳系所含类别。 有很多不同之处,因为每个班级处理与星系相关的不同数据。 因此,我创建了不同的类,它们将具有不同的状态变量,用于这些状态变量的获取器和设置器以及计算和打印数据的方法。 太阳能系统就是一个例子,它给我带来了问题,这就是我在这里所描述的。 当创建GalaxyOneTwo时,它将使用用于GalaxyOne和GalaxyTwo的相同数据,因此我想继承它们的所有变量和方法。 而且因为数据可以以不同的方式组合,所以我需要在GalaxyOneTwo中创建新的方法。 这些是导致我使用继承的许多差异中的一些。 这就是说,容器变量允许组合给我带来问题。 在每个太阳系系统内,会有一个类似的向量,让他们能够访问他们的行星,等等。
编辑:
对于一个专门针对我这里的设计哲学的问题(相对于强调尝试解决当前设计尝试的问题),请参见以下链接:在c ++中为多重继承组合类创建设计的指导
也许你可以改变数据模型来实现基于组件的东西。 每个组件都可以包含您为不同类型提及的相同状态信息。 你可以继承虚拟功能
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...
然后,您可以继承不同类型的太阳系或星系来创建特殊情况并填写虚函数调用
class CoolSolarSystem : public SolarSystem
{
// Special variables
// Fill in the virtual function
void sharedSolarSystemFunction();
};
然后,您可以使用指向特殊类型的指针来填充不同基类型中的容器。 如果虚拟函数调用足够处理那些信息,您应该能够避免转换回特殊类型。
我认为你必须有一个class Galaxy
,一个class SolarSystem
等。而你的GalaxyOne
, GalaxyTwo
SolarSystemOne
, SolarSystemTwo
等只是这些班级的不同对象。
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;
如果我们无法使用这个简单的方法......让我们看看你的:
class GalaxyOneTwo: public GalaxyOne,
public GalaxyTwo,
public PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>{
/* … */
using PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>::solarSystems;
GalaxyOneTwo(){solarSystems.reserve(10);}
};
这里你有三个私人载体:( using
你可以直接访问)
std::vector<SolarSystemOne* > GalaxyOne::solarSystems;
std::vector<SolarSystemTwo* > GalaxyTwo::solarSystems;
std::vector<SolarSystemOneTwo*> solarSystems; //GalaxyOneTwo::solarSystems;
这是你需要的吗? 让它保护?
您需要将“一”和“两”版本的东西之间的常见东西抽象为一组“常见”基类:
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
};
请注意使用virtual
- 要求正确工作的多重继承。
上一篇: Solving design involving multiple inheritance and composite classes in c++
下一篇: Logcat error