Problem mit Vererbung
-
Hi!
Also ich hab folgendes Problem:
Ich hab eine Basisklasse (nennen wir sie mal Typ) mit einem Member (m_type) und eine Reihe von Klassen, die alle auf 'Typ' basieren. So in der Art etwa:
class Typ { public: int m_type; } class Child : public Typ { public: char* m_spezifischeDaten; }
Jetzt habe ich alle Instanzen von 'Typ' in einen Vektor (vector<Typ>typ) getan und kann mit m_type unterscheiden, um welche Klasse es sich genau handelt (also hier beispielsweise 'Child').
Mein Problem ist jetzt nur, die spezifischen Daten der 'Child'-Klasse wieder aus dem Vektor zu bekommen.
Probiere ich Folgendes:
Child child = (Child)vektor[i];
dann bekomme ich einen Error, weil nicht von Typ zu Child gecastet werden kann, nur umgekehrt.
Wie kann ich nun vorgehen? Es sind ziemlich viele Child-Klassen (etwa 15), daher möchte ich meine Code ungern groß verändern, wenn vermeidbar.
Ich wär Euch für jede Hilfe dankbar!
-
Du solltest dich erst mal mit virtuellen methoden und basisklassen beschäftigen.
K.
-
RTTI ist zwar immer ein Zeichen von schlechtem Design, sollte dir aber helfen.
-
RTTI bei deinem Compiler aktivieren
-
Die Instanzen als Zeiger in dem Vektor speichern
-
per dynamic_cast<> zum richtigen Typen casten.
-
per typeid() checken um welchen Typ es sich handelt. Brauchst das nicht selber zu machen.
-
-
Wow, es klappt einwandfrei, tausend Dank auch!
Ich beweg mich ja nun auch schon eine Weile im düsteren Tal des C++, aber von RTTI hab ich noch nie gehört.
Allerdings geb ich dir schon Recht von wegen schlechtem Design, aber es macht schon einiges leichter.Meine Frage wär da nur: Sind das explizite Funktionen für VC++/# oder kann man damit auch unter z.B. kDeveleop kompilieren?
Achja.. was ist denn der gewöhnliche Weg, um Dinge wie diese zu erledigen?Danke auch nochmal!
-
Metabo schrieb:
Hi!
Also ich hab folgendes Problem:
Ich hab eine Basisklasse (nennen wir sie mal Typ) mit einem Member (m_type) und eine Reihe von Klassen, die alle auf 'Typ' basieren. So in der Art etwa:
class Typ { public: int m_type; } class Child : public Typ { public: char* m_spezifischeDaten; }
Jetzt habe ich alle Instanzen von 'Typ' in einen Vektor (vector<Typ>typ) getan und kann mit m_type unterscheiden, um welche Klasse es sich genau handelt (also hier beispielsweise 'Child').
Mein Problem ist jetzt nur, die spezifischen Daten der 'Child'-Klasse wieder aus dem Vektor zu bekommen.
Probiere ich Folgendes:
Child child = (Child)vektor[i];
dann bekomme ich einen Error, weil nicht von Typ zu Child gecastet werden kann, nur umgekehrt.
Wie kann ich nun vorgehen? Es sind ziemlich viele Child-Klassen (etwa 15), daher möchte ich meine Code ungern groß verändern, wenn vermeidbar.
Ich wär Euch für jede Hilfe dankbar!
das geht nat. nicht. wenn du du einen vector<Typ> benutzt, dann sind alle objekte in dem vector vom typ Typ (slicing). das hat 2 gründe:
objekte werden beim einfügen in den vektor kopiert, dabei wird der copy-c'tor entsprechend des statischen typs des objekts ausgeählt, und der ist nunmal Typ. wenn du nun ein Child mittels Typ's copy-c'tor kopierts, dann erhälst du lediglich ein Typ und kein Child.
Grundregel: für polymorphes verhalten brauchst du stets referenzen oder pointer (ggf. auch smart-pointer). das ist auch der grund, warum klassen - abgesehen vom performanceargument - in der regel als referenzen an funktionen übergeben werden sollen. referenzen scheiden hier aus, weil man sie nicht kopieren kann. folglich muss du pointer verwenden. also vector<Typ*>
der zweite grund hängt mit dem ersten zusammen; um objekte in einem fortlaufenden speicherbereich speichern zu können, wie es vector tut, muss das speicherlayout bekannt sein, insbes. die grösse. die kann sich aber bei abgeleiteten klassen ändern.für dein problem gibt es zwei lösungen.
die bessere: redesign, so dass du die objekte weiterhin polymorph behandeln kannst.
die schlechte: dynamic_cast erlaub dir auf simple weise, den cast sicher durchzuführen, wenn er möglich ist (wenn der cast fehlschlägt, kommt 0 heraus). typeid() ist mit abstand die schlechteste variante, die schlägt nähmlich bereits wieder fehl, wenn du eine von Child abgeleitete klasse hast.