Böser DownCast
-
Wenns um die Unterscheidung verschiedener Ableitungen geht, ist mir bis jetzt noch kein Fall vorgekommen, wo mans nicht auch mit Polymorphie hingekriegt hätte -> mein Beitrag in Deinem anderen Thread.
Ich kenn das casten nur aus so Fällen, wo man das wissen über den echten Typen eher formal aber nicht wirklich verliert. A la
class DataSet { //Basisklasse für die Klassen die für den Output //eines Datensatzes zuständig sind class Oput { public: virtual bool Write(DataSet&)=0; } }; class Kunde :public DataSet { class Oput :Oput { public: virtual bool Write(DataSet& daset) //DataSet wird nur wg. der formalen Schnittstelle übergeben { //ansonten 'weißt' Du, das Kunde::Oput //nur für Kunden //zuständig ist (dieses Wissen solltest //Du aber mindestens //mit einem assert oder evtl durch //geschickte Vergabe von //zugriffsrechten absichern) Kunde& kunde= static_cast<Kunde&>(daset); //hier reicht schon ein static cast! //jetzt kannst Du auf die speziellen Schnittstellen des Kunden zugreifen } } };
[ Dieser Beitrag wurde am 08.07.2003 um 22:59 Uhr von kartoffelsack editiert. ]
-
ich hab da in einem projekt z.b. die unterscheidung zwischen pflanze und tier, die beide von lebewesen erben.
jetzt gibt es 10 verschiedene pflanzen und 10 verschiedene tiere.
es gibt noch eine klasse, die bestimmte dinge verwaltet, und je nachdem, ob sie eine bestimmte aufgabe erledigen soll, wenn ein tier sie anspricht, oder eine pflanze, soll sie verschiedene interfaces bereitstellen, bzw. ein interface, das sich bei tier oder pflanze verschieden verhält.jetzt gibt es die funktion:
auto_ptr<Interface> Verwalterklasse::Interface (Lebewesen *l) { if (dynamic_cast<Pflanze*>(l)) return auto_ptr<Interface> (new PflanzenInterface); else return auto_ptr<Interface> (new TierInterface); }
es gibt einfach niemals mehr als Tier und Pflanze, da ist ein dynamic_cast doch gerade recht. ich weiß, es ist entweder tier oder pflanze. und um dem wesen das richtige interface bereitzustellen, wird der typ unterschieden.
(ginge normalerweise auch über funktionsüberladung, aber hierfür ist das design zu kompliziert, zumindest komplizierter, als jetzt beschrieben)
was spricht denn hier dagegen?
-
Der Zweizeiler sieht zwar verlockend einfach aus. Das schlechte daran ist aber imho meist ein grundsätzlicher Designfehler: Du verwirfst das Wissen über die Typen, das Du ja anfangs hast und stellst dann später fest, dass Du's trotzdem wissen muss.
Das ist so wie wenn Dein Zooverwalter nur mitzählt, wie viele Lebewesen er in seinem Tierpark hat und dann jedesmal beim Futterkaufen den Tierhüter anruft und ihn nachgucken lässt wie viele Löwen und Bananenbäume es jetzt genau sind.
-
Man könnte auch Lebewesen eine virtuelle Funktion LebewesenInterface* createInterface() verpassen, damit wär aber jede Lebewesen-Unterklasse von ihrer korrespondierenden Interface-Klasse abhängig. Also baut man sich, wenn man das nicht will, eine Factory (wie du), und muß dann eben mit dem Type switch leben.
-
ich erstelle aber jedesmal neue lebewesen mit einer passenden factory und weiß so gut wie nichts über ihre typen, vor allem dann nicht, wenn ich das system erweitern will. es gibt gras, baum, hund, katze, etc. und ich kann noch immer mehr dazu machen.
das einzige, was ich immer sicher weiß, ist, dass es eine Pflanze oder ein Tier ist. Eines von beiden, kein zwischending. Immer.
und es ist ja auch nur sinnvoll, dem interface der pflanze eine funktion move zu verbieten, oder?
-
Jein. Ich würde in dem Fall sagen, dass ein Lebewesen wissen sollte, ob es sich bewegen kann oder nicht. Dieses Wissen verlagerst Du nach außen in irgendwelche Verwaltungsklassen: Du gugst Dir so ein Lebewesen an gehst dann zu Deinem Verwalter und fragst ihn, was das lebewesen so alles kann. Frag doch das Lebewesen selber! D.h. ich würd mir in Deinem Fall überlegen so ne Art IsMovable-Funktion ins Lebewesen aufzunehmen. Eine Methode Move gäbs aber eben auch in der Basisklasse.
-
das eine pflanze sich nicht bewegt, und das selbst verwalten sollte.
nun aber wenn ich klassen aus einer dll lade, die nicht von mir ist, darf ich der fremden pflanze die bewegung trotzdem nicht erlauben.
darauf kommt es mir an.