c++ - C++中涉及多继承和复合类的解决设计

标签 c++ templates multiple-inheritance composite ambiguity

一段时间以来,我一直在努力解决这个设计问题。我将尽我所能解释我正在尝试做什么以及我所看到的各种方法,我正在尝试什么以及为什么。

我在科学计算环境中工作,在那里我反复处理相同类型的对象。想象一个包含太阳系的星系,每个太阳系都包含行星系统,每个行星系统都包含卫星。为此,我将这种情况视为“有一个”的情况,因此我使用合成使星系可以进入其太阳系,每个太阳系都可以进入可以进入其卫星的行星系统:每个类别是它自己的类。

通常情况下,我正在处理的各种问题包含有关这些对象的不同类型的数据。而且,随着不同类型的数据变得可用,我可以用我的对象做某些事情。因此,当我有可用的数据类型 1 时,我创建了以下类

class GalaxyOne { /* … */ };
class SolarSystemOne { /* … */ };
class PlanetOne{ /* … */ };
class MoonOne{ /* … */ };

当我有可用的数据类型 2 时,我创建
class GalaxyTwo { /* … */ };
class SolarSystemTwo { /* … */ };
class PlanetTwo{ /* … */ };
class MoonTwo{ /* … */ };

每个类的复合方面是通过使用容器变量来处理的,例如包含指向所包含类的指针的 vector 。例如,在每个 Galaxy 类中都会找到。
class GalaxyTwo{ /* … */
protected:
std::vector<SolarSystemTwo*> solarSystems;
/* … */
};

当我想将类组合成高阶类时,困难就来了。
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo{
/* Additional methods */
};

但是,这会在 solarSystems vector 中产生歧义问题,因为 GalaxyOneTwo 将拥有来自 GalaxyOne 和 GalaxyTwo 的版本。此外,它继承的 vector 包含指向非 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。

我可以通过具体和使用来消除这种歧义

原始星系::太阳能系统

每次都引用正确的 vector ,但这不是可取的,因为它需要大量额外的类型和语法。

我曾考虑在每个星系类型和原始星系之间使用友元,但这需要类似级别的冗长写作。

我有一种预感,命名空间可以简化我的代码编写,但我不确定如何定义命名空间,以便在为 GalaxyOneTwo 定义的命名空间中,任何对 solarSystems 的引用都是对
原始星系::太阳能系统

编辑:

请注意,GalaxyOne 和 GalaxyTwo 之间的唯一区别不是 SolarSystems 中包含的类的类型。有很多不同之处,因为每个类(class)处理与星系相关的不同数据。因此,我创建了不同的类,这些类将具有不同的状态变量、getter 和 setter,用于这些状态变量和方法来计算和打印数据。 SolarSystems 是该功能的一个示例,它给我带来了问题,因此这就是我在此处描述的内容。创建 GalaxyOneTwo 时,它将使用用于 GalaxyOne 和 GalaxyTwo 的相同数据,因此我想继承它们的所有变量和方法。由于数据可以以不同方式组合,我需要在 GalaxyOneTwo 中为此创建新方法。这些是导致我使用继承的许多差异中的一些。话虽如此,正是容器变量允许组合给我带来了问题。在每个 SolarSystem 类中,都会有一个类似的 vector ,让他们可以访问他们的行星,依此类推。

编辑:

对于一个专门针对我的一般设计理念的问题(而不是这个问题强调试图解决我当前的设计尝试),请参阅以下链接:
Guidance in creating design for multiple-inheritance composite classes in c++

最佳答案

我想你必须有一个 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);}
};

这里有三个私有(private) vector :(使用 using 可以直接访问)
std::vector<SolarSystemOne*   > GalaxyOne::solarSystems;
std::vector<SolarSystemTwo*   > GalaxyTwo::solarSystems;
std::vector<SolarSystemOneTwo*> solarSystems; //GalaxyOneTwo::solarSystems;

这是你需要的吗?让它受到保护?
enter image description here

关于c++ - C++中涉及多继承和复合类的解决设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15075233/

相关文章:

c++ - 如何处理不同的包围体类型?

c++ - 从重载 + 运算符返回到重载 = 运算符时不调用复制构造函数

c++ - 有条件地删除模板类中的方法

c++ - 如何使父类不重复已执行的祖父方法

design-patterns - 为什么是死亡钻石而不是死亡三角形

c++ - 为什么不推荐使用 isascii()?

c++ - 启动程序和libocci.so.11.1 : cannot open shared object file: No such file or directory

c++ - 如何在模板结构中使用包装的 typedef 修复 C++ 编译

c++ - 需要默认参数值的模板函数的首选设计是什么?

c++ - 在可变参数模板中使用声明