Feststellen, ob Typ des Objekt die Ableitung eines anderen ist
-
Diese Lösung ist nicht nur "unästhetisch", sondern bricht auf mit objektorientierten Prinzipien. Sie ist kaum wartbar, da jede Veränderung in der Vererbungshierarchie quasi ein Neustricken der Funktion bedeutet. Ohne mir intensiv Gedanken gemacht zu haben würde ich sagen, hat eine Funktion dieser Art exponenzielle Komplexität - sowohl bei Auswerten als auch beim Ausprogrammieren. Absoluter Overkill.
Sofern du Ratschläge oder alternative sauberere Lösungen suchst, erklär uns doch bitte mal das Problem und was du vorhast.
Die Ironie an deinem zuletzt geposteten Code ist übrigens, dass du alle Typen statisch benannt hast.
-
Schreib doch mal, was du gerade genau programmieren willst, dann kann man dir mehr helfen. Das was du da programmieren willst, ist nicht wirklich eine Option^^
-
7H3 N4C3R:
Richtig, daher fragte ich auch, denn auf die schlechte Lösung mit den dynamic_cast bin ich selbst schon gekommen.Das Problem lässt sich wie folgt umreissen.
Es gibt verschiedene STL-Listen, welche Pointer auf verschiedene Objekte-Arten beinhalten können.
Hier ein Beispiel mit den Klassen von oben:list<A*> liste_a; //gefuellt mit Pointer auf Objekte vom Typ A, A1, A2 und A11 list<A1*> liste_a1; //gefuellt mit Pointer auf Objekten vom Typ A1 und A11 list<B*> liste_b; //gefuellt mit Pointer auf Objekte vom Typ B1 usw.Objekte sollen nun zwischen den Listen wahlfrei verschoben werden können, wenn das der Typ zulässt.
Die anderen Probleme, die hier auftreten, lassen wir mal aussen vor.
-
da würde doch jeweils ein cast reichen oder?
testen ob der neue Zeiger zum Zeigertyp der Liste passt.
-
Bisher haben alle Deine Beispiele die Eigenschaft dass es nur eine Basisklasse (A) gibt. D.h. es macht IMHO bisher keinen Sinn etwas anderes als nur eine list<A*> zu halten (oder?).
Ansonsten, wenn Du eine list<A1*> haben musst, weisst Du selbst doch schon dass jedes Element dieser Liste von A abgeleitet ist, und demnach dynamic_cast auch garantiert nicht NULL liefern wird.
Irgendwie hab ich die Ahnung, dass das eigentlich einfacher gehen muss

-
:xmas2:
-
Pellaeon schrieb:
da würde doch jeweils ein cast reichen oder?
testen ob der neue Zeiger zum Zeigertyp der Liste passt.So wie ich das sehe nicht. Anscheinend gibt es Ableitungen von T, die aber im Verhalten nicht mehr kompatibel mit T sind (und deshalb in einem Vektor XY unerwünscht). Das ist aber wiederum ein Bruch mit dem Liskov-Substitution-Principle.
Die Problembeschreibung klingt ein wenig nach einem GUI mit Baumansicht, in der Drag and Drop möglich sein soll - nur eben nicht überall hin. Eine Möglichkeit wäre vielleicht, die Typanforderungen der Vektoren zu erhöhen. Sprich z.B. Vektoren mit Zeigern auf B zu halten, wo auch nur Bs reinsollen. Ein Vektor mit Zeigern auf Bs kann dann immernoch in einen Vektor von Zeigern auf As kopiert werden, sofern B von A abgeleitet ist.
-
Da C++ eine Compilersprache und keine Laufzeitsprache ist, werde ich wohl in den sauren Apfel beissen müssen.
Eine ähnliche Idee habe ich damals übrigens verworfen, dass alle Klassen von der gleichen Urklasse abgeleitet sind und ich in den Listen quasi nur Pointer auf die Urklasse halte.
Die sonderbare Listenbildung hat übrigens einen fachlichen Grund.
-
markus.r schrieb:
list<A*> liste_a; //gefuellt mit Pointer auf Objekte vom Typ A, A1, A2 und A11 list<A1*> liste_a1; //gefuellt mit Pointer auf Objekten vom Typ A1 und A11 list<B*> liste_b; //gefuellt mit Pointer auf Objekte vom Typ B1 usw.Objekte sollen nun zwischen den Listen wahlfrei verschoben werden können, wenn das der Typ zulässt.
liste_a und liste_a1 in liste_b würde gar net gehen, Compilefehler, esseidenn du würdest wie wild casten, was du ja nicht machst.
liste_a1 nach liste_a klappt auch ohne Probs. liste_b in eine liste_a* würde auch net kompilieren, also bleibt doch nur liste_a nach liste_a1. Und da würd ein dynamic_cast helfen.
Insofern halt wirklich nur die Typen ausschlaggebend sind und nichts anderesedit: ich seh grad ich vergaß die Basisklasse die alle gemein haben^^
Aber dynamic_cast müsste gehen, insofern man an der Struktur mit den Listen nichts ändern kann
-
7H3 N4C3R schrieb:
Das ist aber wiederum ein Bruch mit dem Liskov-Substitution-Principle.
Wenn ich das richtig verstanden habe, dass das "Liskov-Substitution-Principle" auch als "ist-ein"-Regel bekannt ist, dann stimme ich zu, dass ich die Klasse B etwas voreilig in das Beispiel eingefuehrt.
In dem realen Projekt ist das selbstverstaendlich nicht der Fall.Ich veranschauliche das Problem mal anders.
Es geht hier um das Sortieren von Autos.class Fahrzeug {}; class Sportwagen : Fahrzeug {}; class Porsche : Sportwagen {}; class Ferrari : Sportwagen {}; class Traktor : Fahrzeug {}; //und nun die Listen list<Fahrzeug*> parkplatz; list<Sportwagen*> parkplatz_golfplatz; list<Porsche*> prosche_haendler; list<Traktor*> acker;7H3 N4C3R schrieb:
Die Problembeschreibung klingt ein wenig nach einem GUI mit Baumansicht, in der Drag and Drop möglich sein soll
Exakt das ist eine Teilanwendung davon, sehr gut "hellgesehen":-)
-
Beim LSP (oder ganz grundsätzlich bei öffentlicher Vererbung) geht das "ist ein" gleichher mit "verhält sich wie ein".
Deine GUI könntest du als ein Kompositum darstellen. Wenn etwas in einen Knoten eingefügt werden soll, wir von diesem eine virtuelle accept( T*) Methode aufgerufen. Je nach Knotenklasse entscheidet diese, ob sie das übergebene Objekt akzeptiert oder ob es abwiesen wird.
Beispiel:
class Base { public: virtual void accept( Base*) = 0; }; class A : public Base { public: virtual void accept( Base* b) { if( !dynamic_cast<A*>(b)) { throw std::runtime_error( "Du kommst hier net rein."); } } };So musst du nur noch jeder Knotenklasse beibrigen, was sie akzeptiert und was nicht. Allerdings wird es wieder schwieriger mit der Listenbildung, da du dir im Baum jetzt erstmal alle Blätter suchen musst und daraus dann die Liste formen. Und natürlich kann jeder Knoten selbst entweder ein Blatt oder eine Liste sein. Das bringt ein Kompositum nunmal so mit sich.
-
Eigentlich ist diese Idee nicht so kompliziert bei mir umzusetzen, da die Knoten in der Baumansicht sich lediglich auf das echte davon völlig unabhaengige Datenmodell referenzieren.
Der Angleich wird über eine Controller-View-Modell-Implementierung vollzogen.
Die Baumsicht ist nur eine von diversen Views auf das Modell.
Das Modell habe ich bisher so passiv wie moeglich gehalten aus verschiedenen Gruenden. D.h. es werden bisher Operationen auf das Modell, welche im Wesentlichen STL-Operationen sind, nicht nochmal gekapselt, da diese (zumindest) zur Compile-Zeit typsicherheit komfrortabel sicherstellen.Vielleicht muss ich diesen Ansatz überdenken.
PS: Vielen dank für die freudliche und hochwertige Hilfe.