2013-02-27 7 views
0

я намереваюсь этот вопрос будет более обобщенный вопрос, касающийся моего вопроса найти на следующей ссылке:Руководство по созданию дизайна для множественного наследования составных классов в C++

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

Я работаю с наборами данных связанных с галактиками. Данные о каждой галактике будут содержать информацию о солнечных системах галактики, каждой планетах солнечных систем и каждой планете луны.

Композитное Требование:

От одного этого я полагаю, что мне нужно использовать конструкцию составного класса, где я создаю класс для галактики, солнечные системы, планеты и спутники. Класс галактики будет содержать переменные контейнера-члена, которые содержат указатели на солнечные системы, планеты и луны в дополнение к соответствующим членам-получателям и сеттерам для этих переменных контейнера. Солнечная система имела бы аналогично разработанные контейнерные переменные-члены, содержащие указатели на содержащиеся планеты и луны с геттерами и сеттерами и так далее с планетами.

Множественный-Наследование Требование:

Типы входных данных, которые я использую для каждого из этих классов не является постоянным. Время от времени у меня есть данные типа 1 и в других случаях, возможно, данные типа 2. Различные виды данных, которые у меня есть для любого заданного проекта, могут меняться со временем. Чтобы избежать появления монстра растущего класса галактик, который получает новые переменные-члены и функции для каждого типа данных, доступных для каждого проекта, а также всех старых (и, возможно, неиспользуемых в текущем проекте), я хочу разбить галактику, solarSystem , классы планет и луны переходят в связанные классы, каждый из которых специализируется на определенном наборе данных.

Таким образом, если я рассматриваю два доступных набора данных, доступных мне мне, data1 и data2, я могу выбрать создание конкретных версий каждого класса для каждого набора данных.

Мне нравится этот подход, потому что, если у меня есть новый проект, который требует комбинации данных1 и data2, я могу создать новые классы для классов галактики, соларСистемы, планеты и луны, которые раньше унаследовали от обоих соответствующих типов. Что-то вроде следующего.

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.

Возможные решения:

Шаблон Base class- Сделать шаблон базового класса PrimitiveGalaxy, PrimitiveSolarSystem, PrimitivePlanet, PrimitiveMoon, которые содержат все контейнера переменных и соответствующих геттеров и сеттеры, из которого все последующие классы наследуют , Это тот подход, который я использовал в ссылке выше, и ее проблемы можно найти там.

Virtual Base class- Было предложено, чтобы создать базовый класс, который содержит все общие функции во всех видах Галактик, SolarSystems, планет и лун. Это включало бы контейнерные переменные в соответствующие указатели, а также их получатели и сеттеры. Таким образом, указатели могли бы использоваться для указания базового класса каждого типа и до тех пор, пока базовый тип содержал виртуальные функции для всех необходимых более поздних функций, тогда я мог бы избежать применения моих указателей к более сложным типам.

Моя забота об этом подходе заключается в том, что он требует не только записи виртуальных функций в базовом классе для каждой новой функции в производных классах, но также и не каждый производный класс будет определять каждую виртуальную функцию в базовом классе.

До сих пор вышеупомянутое возможное решение - единственное, что я сейчас хорошо понимаю, чтобы опубликовать его.

Я хочу решение, которое позволяет использовать гибкий код, который не требует сложного синтаксиса, и который не требует каждой растущей и неуправляемой серии очень больших определений классов. Мои проекты регулярно включают новые виды данных, поэтому я хочу иметь возможность легко создавать новые парсеры для этих новых данных и с готовностью включать данные в мои различные проекты, используя классы Galaxy, SolarSystem, Planet и Moon.

+0

Если вы действительно хотите использовать эту модель множественного наследования, то ваш единственный выбор: 1. лить или 2. внутри 'GalaxyOne' использовать только контейнеры, содержащие' SolarSystemOneTwo' –

+0

Я не установленный на множественном наследовании по какой-либо причине, кроме того, что у меня есть лучшая ручка. Не могли бы вы рассказать о том, как я могу это сделать с помощью кастинга? Я не очень хорошо знаком с этим. – PhiloEpisteme

+0

@ vckngs7 Этот вопрос действительно отличается от вашего предыдущего? – jogojapan

ответ

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 и магазин это в указателе Галактики и все еще имеют доступ к соответствующим функциям. Аналогичная стратегия используется с SolarSystems, Planets and Moons.