Zyklische Abhängigkeit zwischen Klassentemplates
-
Guten Morgen zusammen,
ich habe zwei Klassentemplates, Vector und Point, die über den Konstruktor und
operator=in einander konvertierbar sein sollen.Das sieht ungefähr so aus:
vector.h
#include "point.h" template <typename NT> class Vector { // some stuff public: template <typename OT> Vector(Point<OT> point) /* Wertzuweisungen */; // more stuff };point.h
#include "vector.h" template <typename NT> class Point { // some stuff public: template <typename OT> Point(Vector<OT> vector) /* Wertzuweisungen */; // more stuff };Die zyklische Abhängigkeit ist sehr offensichtlich, jedoch müssen Klassentemplates meines Wissens komplett in der Header Datei definiert sein und daher weiß ich nicht, wie ich dieses Problem lösen könnte.
Ich bin bereits auf die Idee gekommen, die Definition der gemeinsamen Funktionen in eine dritte Headerdatei auszulagern, jedoch scheitere ich hierbei an der Syntax zur Definition von Konstruktoren von Klassentemplates außerhalb der Klassentemplatedefinition.
-
Google mal nach forward declaration. Gibts auch für Templates

Wenn die beiden Templates so eng miteinander verwoben sind, dass die hin- und herkonvertzierung Sinn macht, dann schadet es auch nicht, sie in den selben Header zu packen.
-
pumuckl schrieb:
Google mal nach forward declaration. Gibts auch für Templates

Dessen bin ich mir bewusst, nur weiß ich nicht, wo ich dann die Definition inkludieren soll, da ich Member-Zugriff brauche.
pumuckl schrieb:
Wenn die beiden Templates so eng miteinander verwoben sind, dass die hin- und herkonvertzierung Sinn macht, dann schadet es auch nicht, sie in den selben Header zu packen.
Beide Header sind recht groß geraten, daher würde ich es der Ordnung und Lesbarkeit halber vorziehen, sie von einander zu trennen.
-
ZyklischRatlos schrieb:
Beide Header sind recht groß geraten, daher würde ich es der Ordnung und Lesbarkeit halber vorziehen, sie von einander zu trennen.
Okay, dann drück ichs mal anders aus: Wenn die beiden Dinge so extrem eng gekoppelt sind, sind sie nur zwei Namen für fast das Gleiche. Dann macht es nur der Übersichtlichkeit wegen Sinn, den einen Header der Vector/Point Geschichte aufzuteilen, und dann musst du offenbar was anderes finden als die Trennung nach den beiden Namen, die du vergeben hast. (z.B. in Klassen(template-)definition und Methodendefinition)
Wenn du allerdings schon sagst, dass die Header schon so groß sind (wie viele Zeilen ist "groß"?), deutet das auf ein Designproblem hin. Hast du das SRP (Single Responsibility Principle) beachtet? Was ist denn alles drin in deinen Klassen?
-
pumuckl schrieb:
Wenn du allerdings schon sagst, dass die Header schon so groß sind (wie viele Zeilen ist "groß"?), deutet das auf ein Designproblem hin. Hast du das SRP (Single Responsibility Principle) beachtet? Was ist denn alles drin in deinen Klassen?
"Groß" sind bisher ca. 150 (Point) und 200 (Vector) Zeilen Code, hinzu wird etwa das Dreifache an Kommentaren für die Dokumentation kommen.
Enthalten sind momentan Zuweisungs-, Rechen- und Vergleichsoperatoren. Ergänzt werden später noch Funktionen, die beide Klassen betreffen (die angesprochene Konvertierung, Rechenoperationen mit beiden Typen). Das mag für die meisten nicht viel sein, ich persönlich bevorzuge jedoch kleine Header.Eine Vererbung nicht möglich, die einzige Gemeinsamkeit zwischen beiden ist, dass sie zwei Koordinaten teilen.
Die Konvertierung soll den Zweck erfüllen, aus einem Punkt einen Ortsvektor bzw. aus einem Ortsvektor einen Punkt zu erstellen.
pumuckl schrieb:
Okay, dann drück ichs mal anders aus: Wenn die beiden Dinge so extrem eng gekoppelt sind, sind sie nur zwei Namen für fast das Gleiche. Dann macht es nur der Übersichtlichkeit wegen Sinn, den einen Header der Vector/Point Geschichte aufzuteilen, und dann musst du offenbar was anderes finden als die Trennung nach den beiden Namen, die du vergeben hast. (z.B. in Klassen(template-)definition und Methodendefinition)
Nonmember-Funktionen in einen extra Header zu schreiben, ist eine Idee, mit der ich mich durchaus anfreunden kann, danke.
-
Wo sind eigentlich die Unterschiede zwischen der Punkt und der Vektor Klasse?
-
ZyklischRatlos schrieb:
"Groß" sind bisher ca. 150 (Point) und 200 (Vector) Zeilen Code,
Das ist moderat und in Ordnung.
hinzu wird etwa das Dreifache an Kommentaren für die Dokumentation kommen.
Das ist extrem viel. Was soll denn da alles rein, was man nicht auch aus dem Code lesen kann? (Was man gut aus dem Code lesen kann, sollte nicht mehr in die Kommentare, um Redundanz zu vermeiden. Was man nicht gut aus dem Code lesen kann, sollte man möglichst durch aussagekräftigen Code lesbar machen. Guter Code kommentiert sich größtenteils selbst)
Ergänzt werden später noch Funktionen, die beide Klassen betreffen (die angesprochene Konvertierung, Rechenoperationen mit beiden Typen).
Die sollten in einen separaten Header. Vor allem wenn du das mit der Konvertierung einrichten kannst, sie als separate Funktionen zu implementieren, dann entkoppelst du Point und Vector voneinander, sie brauchen dann ja nichts voneinander zu wissen.
Die Konvertierung soll den Zweck erfüllen, aus einem Punkt einen Ortsvektor bzw. aus einem Ortsvektor einen Punkt zu erstellen.
Wo ist der Unterschied? Die Beziehung Punkt<->Ortsvector ist doch eine 1:1 Beziehung, wozu braucht man dann noch die Unterscheidung?
-
pumuckl schrieb:
Das ist extrem viel. Was soll denn da alles rein, was man nicht auch aus dem Code lesen kann? (Was man gut aus dem Code lesen kann, sollte nicht mehr in die Kommentare, um Redundanz zu vermeiden. Was man nicht gut aus dem Code lesen kann, sollte man möglichst durch aussagekräftigen Code lesbar machen. Guter Code kommentiert sich größtenteils selbst)
Die Klassen sind Bestandteil einer Library, die mit Doxygen dokumentiert wird, folglich findet die Dokumentation direkt in der Header Datei statt. Auf jede Funktion kommen mindestens 3 Zeilen Dokumentation, abhängig von Rückgabewert, Parameteranzahl und Aufgabe.
pumuckl schrieb:
Wo ist der Unterschied? Die Beziehung Punkt<->Ortsvector ist doch eine 1:1 Beziehung, wozu braucht man dann noch die Unterscheidung?
cooky451 schrieb:
Wo sind eigentlich die Unterschiede zwischen der Punkt und der Vektor Klasse?
In dem Kontext ist es ein Unterschied in der Verwendung. Punkte sollen als konkrete Positionen im Fenster (GUI) verwendet werden, sie sollen abgesehen von der Addition mit Vektoren (Verschiebung) keine weiteren Rechenoperationen enthalten, nur zweidimensional sein und es soll Funktionen geben, die aus diversen Punkten neue Punkte bestimmen. (z.B. Rotation)
Vektoren hingegen sind dreidimensional und vor allem mathematische Objekte, die in erster Linie dem Mathematischen, von Dimensions- bis Volumenberechnung. Außerdem werden sie genutzt, um Dimensionen darzustellen.Beide Typen sollen in einander konvertierbar sein, um beide mathematischen Aspekte zu vereinen, die Verwendung beider Typen ist jedoch grundverschieden.
Ich hoffe, meine Absichten dahinter verständlich erklärt zu haben.
Wie gesagt: die einzigen Gemeinsamkeiten sind die X und Y Koordinate.