Решение дизайна, включающего множественное наследование и составные классы в 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 solarSystems;
/* … */
};

Трудность возникает, когда я хочу объединить классы в классы более высокого порядка.

class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo{
/* Additional methods */
};

Однако это создает проблему неоднозначности в векторе solarSystems, поскольку GalaxyOneTwo будет иметь его версию от GalaxyOne и GalaxyTwo. Кроме того, векторы, которые он наследует, содержат указатели на объекты, которые не относятся к типу SolarSystemOneTwo, что необходимо. Итак, я подумал, что смогу создать шаблонный класс, который наследует все мои объекты, откуда я помещаю все свои переменные контейнера.

template
    class PrimitiveGalaxy {
    private:
        std::vector solarSystems
};

class GalaxyOne: public PrimitiveGalaxy {
    /* No longer defining any container variables for composition */
};

Этот подход очень хорошо работает для тех основных типов Galaxy (GalaxyOne и GalaxyTwo). Однако всякий раз, когда я пытаюсь создать комбинированный тип галактики, я получаю все виды неоднозначности.

class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo, public     PrimitiveGalaxy{
    /* … */
};

Я получаю неоднозначность, если использую solarSystems в любом методе, определенном в GalaxyOneTwo, потому что он определяется три раза, один раз через каждую унаследованную версию от GalaxyOne и GalaxyTwo и третий раз через GalaxyOneTwo.

Я могу избавиться от этой двусмысленности, будучи конкретным и используя

PrimitiveGalaxy :: SolarSystems

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

Я рассмотрел использование дружбы между каждым типом галактики и примитивной галактикой, но это требует подобного уровня многословного письма.

Я догадываюсь, что пространства имен могут упростить мое написание кода, но я не уверен, как определить пространство имен так, чтобы в пространстве имен, определенном для GalaxyOneTwo, любая ссылка на solarSystems была ссылкой на PrimitiveGalaxy :: solarSystems

Редактировать:

Обратите внимание, что единственная разница между GalaxyOne и GalaxyTwo - это НЕ тип класса, содержащегося в solarSystems. Есть много различий, потому что каждый класс имеет дело с различными данными, относящимися к галактике. Таким образом, я создаю разные классы, которые будут иметь разные переменные состояния, методы получения и установки для этих переменных состояния и методы для вычисления и печати данных. SolarSystems является примером функции, которая доставляет мне проблемы, поэтому я описал ее здесь. Когда GalaxyOneTwo создан, он будет использовать те же данные, которые используются для GalaxyOne и для GalaxyTwo, и поэтому я хочу наследовать все их переменные и методы. И поскольку данные могут комбинироваться различными способами, мне нужно создать новые методы для этого в GalaxyOneTwo. Вот некоторые из многих различий, которые побуждают меня использовать наследование. Это, как говорится, это контейнерные переменные, которые позволяют для композиции, которые вызывают у меня проблемы. Внутри каждого класса solarSystem будет один и тот же вектор, дающий им доступ к их планетам, и так далее, и тому подобное.

Редактировать:

Для вопроса, специально посвященного моей философии дизайна здесь в целом (в отличие от этих вопросов акцент на попытке разрешить мою текущую попытку проектирования), смотрите следующую ссылку:Руководство по созданию дизайна для составных классов с множественным наследованием в C ++

Ответы на вопрос(4)

Ваш ответ на вопрос