Ich habe mit diesem Designproblem für einige Zeit gekämpft. Ich werde mein bestes geben, um zu erklären, was ich versuche zu tun, und die verschiedenen, die ich gesehen habe, näherten sich, was ich versuche und warum.Lösen von Design mit mehreren Vererbung und zusammengesetzten Klassen in C++
Ich arbeite in einer wissenschaftlichen Computerumgebung, in der ich wiederholt mit den gleichen Arten von Objekten arbeite. Stellen Sie sich eine Galaxie vor, die Sonnensysteme enthält, jedes Sonnensystem enthält Planetensysteme und jedes Planetensystem enthält Monde. Zu diesem Zweck denke ich an die Situation als "hat eine" Situation, und so habe ich Komposition verwendet, um der Galaxie Zugang zu ihren Sonnensystemen zu geben, und jedes Sonnensystem Zugang zu den Planetensystemen, die Zugang zu ihren Monden haben: jede Kategorie eine eigene Klasse sein.
Es ist oft der Fall, dass die verschiedenen Probleme, an denen ich arbeite, verschiedene Arten von Daten über diese Objekte enthalten. Und wenn verschiedene Arten von Daten verfügbar werden, kann ich bestimmte Dinge mit meinen Objekten tun. Also, wenn ich Datentyp 1 zur Verfügung zu mir haben erstelle ich die folgenden Klassen
class GalaxyOne { /* … */ };
class SolarSystemOne { /* … */ };
class PlanetOne{ /* … */ };
class MoonOne{ /* … */ };
Und wenn ich Datentyp 2 zur Verfügung zu mir habe ich schaffen
class GalaxyTwo { /* … */ };
class SolarSystemTwo { /* … */ };
class PlanetTwo{ /* … */ };
class MoonTwo{ /* … */ };
Die Verbund Aspekte jeder Klasse behandelt werden mit Containervariablen wie Vektoren, die Zeiger auf die enthaltenen Klassen enthalten. Zum Beispiel würde man innerhalb jeder Galaxy-Klasse finden.
class GalaxyTwo{ /* … */
protected:
std::vector<SolarSystemTwo*> solarSystems;
/* … */
};
Die Schwierigkeit kommt, wenn ich Klassen in Klassen höherer Ordnung kombinieren möchte.
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo{
/* Additional methods */
};
Dies schafft jedoch ein Problem der Mehrdeutigkeit in den Solarsystemen Vektor weil GalaxyOneTwo eine Version davon aus GalaxyOne und GalaxyTwo haben würde. Darüber hinaus enthalten die Vektoren, die er erbt, Zeiger auf Objekte, die nicht vom Typ SolarSystemOneTwo sind, die benötigt würden. Also, ich dachte, ich könnte eine Template-Klasse erstellen, die alle meine Objekte erben von wo ich alle meine Container-Variablen.
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 */
};
Dieser Ansatz funktioniert sehr gut für die grundlegenden Galaxy-Typen (GalaxyOne und GalaxyTwo). Wenn ich jedoch versuche, den kombinierten Galaxietyp zu erstellen, bekomme ich alle Arten von Zweideutigkeiten.
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo, public PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>{
/* … */
};
ich Mehrdeutigkeit, wenn ich innerhalb eines solarsystems-Methode definiert in GalaxyOneTwo verwenden, da es dreimal definiert ist, einmal durch jede geerbte Version von GalaxyOne und GalaxyTwo und ein drittes Mal durch GalaxyOneTwo.
I diese Zweideutigkeit bekommen kann befreien, indem spezifische und mehr
PrimitiveGalaxy :: Solarsysteme
jedes Mal auf den richtigen Vektor mit Bezug zu nehmen, aber dies ist nicht wünschenswert, da es eine Menge zusätzlicher Eingabe erfordert und Syntax.
Ich habe überlegt, Freundschaft zwischen jedem Galaxietyp und der primitiven Galaxie zu verwenden, aber dies erfordert eine ähnliche Ebene des ausführlichen Schreibens.
Ich habe das Gefühl, dass Namespaces mein Schreiben von Code vereinfachen kann, aber ich bin nicht sicher, wie Sie den Namespace zu definieren, so dass innerhalb eines Namespace für GalaxyOneTwo definiert, dass jede Bezugnahme auf solarsystems ist ein Verweis auf PrimitiveGalaxy :: Solarsysteme
Bearbeiten:
Bitte beachten Sie, der einzige Unterschied zwischen GalaxyOne und GalaxyTwo ist nicht der Typ der Klasse in SolarSystems enthalten. Es gibt viele Unterschiede, da jede Klasse sich mit verschiedenen Daten befasst, die für die Galaxie relevant sind. Daher erstelle ich verschiedene Klassen, die verschiedene Zustandsvariablen, Getter und Setter für diese Zustandsvariablen und Methoden zum Berechnen und Drucken von Daten haben. solarSystems ist ein Beispiel für die Funktion, die mir Probleme bereitet, so wie ich es hier beschrieben habe. Wenn GalaxyOneTwo erstellt wird, wird es dieselben Daten verwenden, die für GalaxyOne und für GalaxyTwo verwendet werden, und daher möchte ich alle ihre Variablen und Methoden erben. Und weil die Daten auf verschiedene Arten kombiniert werden können, muss ich dafür innerhalb von GalaxyOneTwo neue Methoden entwickeln. Dies sind einige der vielen Unterschiede, die mich dazu führen, Vererbung zu verwenden. Davon abgesehen sind es die Containervariablen, die eine Komposition ermöglichen, die mir Probleme bereiten. Innerhalb jeder solarSystem-Klasse wird es einen ähnlichen Vektor geben, der ihnen Zugang zu ihren Planeten gibt, und so weiter und so fort.
Edit:
Für eine Frage speziell auf meine Design-Philosophie gewidmet hier im Allgemeinen (im Gegensatz zu diesen Fragen Schwerpunkt im Gegensatz zu versuchen, meinen aktuelles Design Versuch zu lösen) ist unter folgendem Link: Guidance in creating design for multiple-inheritance composite classes in c++
Was soll ein GalaxyOneTwo sein? Eine Sammlung von verschiedenen Arten von Galaxien oder eine gemeinsame Schnittstelle (oder Implementierung) der beiden? Welche Art von Operationen möchten Sie auf einem Galaxy One tun? –
Wie ich oben beschreiben wollte, ist GalaxyOneTwo eine Galaxie, die nicht nur Zugriff auf die Elementfunktionen von GalaxyOne und GalaxyTwo hat, sondern auch die Möglichkeit bietet, die gleichen Daten zu verarbeiten nur zu GalaxyOne und GalaxyTwo, um kompliziertere Datenanalyse durchzuführen. – PhiloEpisteme
Nein, ich frage mich: Was ist das, was Sie versuchen, mit Vererbung zu modellieren? Eine Art Galaxie mit allen Arten von Sonnensystemen in Galaxie eins und Galaxie zwei? Wenn ich nach der Art von Operationen frage, meine ich ein konkretes Beispiel, wie zB die Gesamtmasse der Galaxie, Leuchtkraft, Sternenzählung und so weiter. Wenn Sie Beispiele dafür geben, welche Art von kombinierten Funktionen GalaxyOneTwo haben sollte, können Sie bessere Antworten erhalten. –