在c ++中为多继承组合类创建设计的指导 [英] Guidance in creating design for multiple-inheritance composite classes in c++

查看:253
本文介绍了在c ++中为多继承组合类创建设计的指导的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算将此问题作为一个更笼统的问题,我的问题在以下链接中找到:



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



我正在使用与星系相关的数据集。



复合要求: / p>

从这一点我想,我需要使用复合类设计,我为银河,太阳系,行星和卫星创建一个类。 galaxy类将包含成员容器变量,其中包含指向太阳系,行星和卫星的指针,以及这些容器变量的适当的成员getter和setter函数。太阳系将具有类似设计的成员容器变量,其包含指向所包含的行星和具有吸气和设定器的卫星的指针,以及行星也是如此。



strong>多继承要求:



我用于每个类的输入数据类型不是常数。有时我有类型1的数据和其他时间也许类型2的数据。我对任何给定项目的不同种类的数据可能随时间的推移而改变。为了避免拥有一个怪异增长的星系类,它为每个项目以及所有的旧项目(可能在当前项目中未使用)的每种类型的数据获取新的成员变量和函数,我想打破星系,太阳系,行星和月亮类分成相关的类,每个专门用于处理一组特定的数据。



因此,如果我考虑两个可能的数据集,data1和data2,我可以选择为每个数据集创建每个类的特定版本。



我喜欢这种方法,因为如果我有一个新项目需要data1和data2的组合,我可以为银河系,solarySystem,行星和月亮类创建新类继承自两个相关类型之前。像下面这样。

  class GalaxyOneTwo:public GalaxyOne,public GalaxyTwo {/ *。 。 。 * /}; 
class SolarSystemOneTwo:public SolarSystemTwo,public SolarSystemOne {/ *。 。 。 * /};
class PlanetOneTwo:public PlanetTwo,public PlanetOne {/ *。 。 。 * /};
class MoonOneTwo:public MoonTwo,public MoonOne {/ *。 。 。 。* /};

这让我可以访问所有的veriables和方法来处理data1和data2,进一步定义用于处理由data1和data2的组合产生的新属性的变量和方法。



问题:

这些设计思想,复合要求和多重继承要求对我自己都有好处。但是,我真的想使用两者。使用两者的困难是,GalaxyOne中的那些允许访问SolarSystemOne的指针的容器变量对GalaxyOneTwo没有用,因为SolarSystemOne中的指针类型不允许访问SolarSystemOneTwo的成员函数。



可能的解决方案:



模板基类 -
创建一个模板基类PrimitiveGalaxy,PrimitiveSolarSystem,PrimitivePlanet,PrimitiveMoon,它包含所有其他类继承的所有容器变量和相关的getter和setter。这是我在上面发布的链接中使用的方法,它的问题可以在那里找到。



虚拟基类 -
有人建议我创建一个基类,它包含所有种类的星系,太阳系,行星和月亮中的所有共享函数。这将包括到相关指针的容器变量以及它们的getter和setter。通过这样做,指针可以用于指向每个类型的基类,只要基类型包含所有必要的后定义函数的虚函数,那么我可以避免将我的指针转换为更复杂的类型。



我对这种方法的关注是,它不仅需要在基类中为派生类中的每个新函数编写虚函数,而且不是每个派生类都将定义每个虚函数函数。



到目前为止,上述可能的解决方案是我目前唯一能够发布的解决方案。



我想要一个解决方案,允许灵活的代码,不需要复杂的语法,并且不需要一个不断增长和无法管理的一系列非常大的类定义。我的项目经常包括新的数据,所以我想能够轻松地为这些新数据创建新的解析器,并且可以使用Galaxy,SolarSystem,Planet和Moon类将这些数据包含到各个项目中。

解决方案

我能够通过使用抽象基类来解决我的问题。抽象基类包含所有容器变量和适当的getter和setter变量。此外,抽象基类定义了将在任何派生类中使用的所有方法的抽象方法。这些方法被预处理器指令包围,只要包括那些虚拟函数,如果还包括定义所述函数的适当的头文件,这将阻止进一步的抽象类。

  class Galaxy {
protected:
std :: vector< SolarSystem *>太阳系
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

在这里输入代码

};

GalaxyOne.h

  #define GALAXYONE 
class GalaxyOne {
protected:
/ * GalaxyOne的私有变量* /
public:
void aGalaxyOneMethod //不再抽象
};

GalaxyTwo.h

  #define GALAXYTWO 
class GalaxyTWO {
protected:
/ * GalaxyTwo的私有变量* /
public:
void aGalaxyTwoMethod //不再抽象
};

GalaxyOneTwo.h

  #define GALAXYONE 
#define GALAXYTWO
#define GALAXYONETWO
class GalaxyOneTwo:虚拟公众GalaxyOne,虚拟公众GalaxyTwo {
protected:
/ *用于GalaxyOneTwo的私有变量* /
public:
void aGalaxyOneTwoMethod(); //不再抽象
};

此方案允许创建一个类型为GalaxyOneTwo的对象,并将其存储在银河指针可以访问适当的功能。类似的策略用于SolarSystems,Planets和Moons


I intend this question to be a more generalized question relating to my question found at the following link:

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

I am working with data sets related to Galaxies. The data about each galaxy will contain information about a galaxie's solar systems, each solar systems planets and each planets moons.

The Composite Requirement:

From this alone I imagine that I need to use composite class design where I create a class for the galaxy, the solar systems, the planets and the moons. The galaxy class will contain member container variables which contain pointers to solar systems, planets and moons in addition to the appropriate member getter and setter functions for those container variables. The solar system would have a similarly designed member container variables containing pointers to the contained planets and moons with the getters and setters, and so forth with the planets as well.

The Multiple-Inheritence Requirement:

The types of input data that I use for each of these classes is not constant. At times I have data of type 1 and other times perhaps data of type 2. The different kinds of data that I have for any given project may change as time goes on. In order to avoid having a monsterously growing galaxy class which gets new member variables and functions for each not type of data available for each project as well all of the old (and possibly unused in the current project) I want to break the galaxy, solarSystem, planet and moon classes up into related classes each specialized to deal with a certain set of data.

Thus, if I consider two of the possible data sets available to me me, data1 and data2, I may choose to create specific versions of each class for each data set.

I like this approach because if I have a new project which requires the combination of data1 and data2 I can create new classes for the galaxy, solarySystem, planet and moon classes that inherit from both of the relevent types before. Something like the following.

class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo { /* . . .  */ };
class SolarSystemOneTwo: public SolarSystemTwo, public SolarSystemOne{ /* . . . */};
class PlanetOneTwo: public PlanetTwo, public PlanetOne{ /* . . . */ };
class MoonOneTwo: public MoonTwo, public MoonOne{ /* . . . .*/};

This gives me access to all of the veriables and methods for dealing with data1 and data2 AND I can then further define variables and methods for dealing with new properties that arise out of the combination of data1 and data2.

The Problem:

Each of these design ideas, the composite requirement and the multiple-inheritence requirement have worked well on their own for me. But, I would really like to use both. The difficulty in using both is that those container variables within GalaxyOne that give it access to the pointers of SolarSystemOne are of no use to GalaxyOneTwo because the types of pointers in SolarSystemOne do not give access to the member functions of SolarSystemOneTwo.

Possible Solutions:

Template Base Class- Make a template base class PrimitiveGalaxy, PrimitiveSolarSystem, PrimitivePlanet, PrimitiveMoon which contain all of the container variables and relevant getters and setters from which all further classes inherit. This is the approach I used in the link posted above, and its problems can be found there.

Virtual Base Class- It has been proposed that I create a base class which contains all of the shared functions across all kinds of Galaxies, SolarSystems, Planets and Moons. This would include container variables to the relevant pointers as well as their getters and setters. By doing this the pointers could be used to point to the base class of each type and so long as the base type contained virtual functions for all necessary later defined functions, then I could avoid casting my pointers to the more complex types.

My concern for this approach is that it not only requires the writing of virtual functions in the base class for every new function in derived classes but also that not every derived class will define each virtual function in the base class.

Thus far, the above possible solution is the only one I currently understand well enough to post.

I want a solution that allows for flexible code that does not require complicated syntax and that does not require an every growing and unmanageable series of very large class definitions. My projects regularly include new kinds of data so I want to be able to easily create new parsers for this new data and readily be able to include the data into my various projects using the Galaxy, SolarSystem, Planet and Moon classes.

解决方案

I was able to solve my problem by using an abstract base class. The abstract base class contains all of my container variables and appropriate getter and setter variables. In addition, the abstract base class defines abstract methods for all methods that will be used in any derived class. These methods are surrounded by preprocessor directives that only include those virtual functions if the appropriate header file is also included that defines said functions, this prevents further abstract classes.

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
};

This scheme allows one to create an object of type GalaxyOneTwo and store it in a pointer of Galaxy and still have access to the appropriate functions. A similar strategy is used with SolarSystems, Planets and Moons

这篇关于在c ++中为多继承组合类创建设计的指导的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆