【问题标题】:Guidance in creating design for multiple-inheritance composite classes in c++在 C++ 中为多继承复合类创建设计的指南
【发布时间】:2013-02-27 20:07:52
【问题描述】:

我打算将此问题作为与我在以下链接中找到的问题相关的更笼统的问题:

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

我正在处理与 Galaxies 相关的数据集。每个星系的数据将包含有关星系的太阳系、每个太阳系行星和每个行星卫星的信息。

复合要求:

仅凭这一点,我想我需要使用复合类设计,在其中为银河系、太阳系、行星和卫星创建一个类。除了这些容器变量的适当成员 getter 和 setter 函数之外,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 类轻松地将数据包含到我的各种项目中。

【问题讨论】:

  • 如果您真的希望使用这种多重继承模型,您唯一的选择是 1. cast 或 2. 在 GalaxyOne 内仅使用包含 SolarSystemOneTwo 的容器
  • 我没有设置多重继承,除了这是我最好的处理方式。您能否详细说明我如何通过铸造来做到这一点?我不是很熟悉。
  • @vckngs7 这个问题和你之前的问题真的不同吗?
  • 我觉得它们之间有不同的联系。我在这里问如何更好地设计我的程序。我的另一个问题是关于如何修复特定的实现。
  • "我对这种方法的担忧是,它不仅需要为派生类中的每个新函数在基类中编写虚函数,而且并非每个派生类都会在基类中定义每个虚函数。基类。” --- 这句话似乎是凭空变出来的。你能用一个具体的代码示例来展示它吗?

标签: c++ templates multiple-inheritance composition ambiguity


【解决方案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 和 Moons 使用了类似的策略

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2012-08-10
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多