Besere Lösung gesucht (Polymorphie)
-
Hallo Leute,
ich habe folgendes Minimalbeispiel. Es soll eine Basisklasse geben, die etwas tut (hier Object, diese initialisiert ihren member im c'tor).
Nun gibt es abgeleitete abstrakte Klassen die etwas können sollen (wie Creature, soll hallo sagen können) und ihre Ableitungen (Human und Chicken) die letztentlich hallo-sagen implementieren.Angenommen zur Initialisierung von Object ist noch nicht bekannt was einmal mit Object und deren membern geschehen soll. Diese sollen unterschiedlich interpretiert werden können. (Angedeutet dadurch, dass member bei Chicken die Körner sind, und bei Human die Dollers in der Tasche).
Wie kann ich die Umwandlung von Object zu Chicken bzw zu Human elegant vornehmen, sodass SayHello() von Creature die jeweilige polymorphe Methode aufruft?
Meine einzige Idee war den Copy-Konstruktur zu nutzen und Chicken bzw Human neu anzulegen. Hat jmd eine besser Idee?
Viele Grüße,
K.#include <iostream> class Object { public: Object():member(4) {} virtual ~Object() { std::cout << "Object died." << std::endl; } protected: int member; }; class Creature : public Object { public: virtual void SayHello() const = 0; }; class Human : public Creature { public: ~Human() { std::cout << "Human died." << std::endl; } void SayHello() const { std::cout << "Jo, hello! I have "<< member <<" $ in my pocket." << std::endl; } }; class Chicken : public Creature { public: ~Chicken() { std::cout << "Chicken died." << std::endl; } void SayHello() const { std::cout << "Put put! I search for " << member << " grains."<< std::endl; } }; int main() { //zur Initialisierung weiß ich noch nicht dass dies eine Creature wird, es könnte auch z.B. ein Auto werden. Das kann dann nicht Hallo sagen. Object o; //nun ist die initislierung abgeschlossen und ich möchte o als Human und als Chicken behandeln. const Creature * livingThing; livingThing = new Chicken( *static_cast<Chicken*>(&o) ); //livingThing = reinterpret_cast<Chicken*>(&o) ; livingThing->SayHello(); delete livingThing; livingThing = new Human( *static_cast<Human*>(&o) ); livingThing->SayHello(); delete livingThing; return 0; }
-
Das geht so nicht.
"o" vom Typ Object kann nicht zum Typ Human oder Chicken werden. In dieser Form ist dein Sourcecode fehlerhaft.
Beschreib doch mal, was du wirklich machen willst (abseits von Menschen und Hühnern), dann können wir dir sicherlich eine schöne Lösung nennen!

-
So funktioniert Polymorphie nicht in C++. Ein Basisklassenobjekt ist keine Stammzelle, die durch geeignetes Casten zur Leberzelle wird.
//nun ist die initislierung abgeschlossen und ich möchte o als Human und als Chicken behandeln. const Creature * livingThing; livingThing = new Chicken( *static_cast<Chicken*>(&o) );new Chickenruft automatisch den Basisklassenkonstruktor vonCreatureundObjectauf. Das Objektoist nicht noetig. Alsoconst Creature * livingThing; livingThing = new Chicken;von Object zu Chicken bzw zu Human
Wann bitte werden denn Huehner zu Menschen. Ok, es gibt Werwoelfe. Aber sie verwandeln sich, d.h. es sollte eine Funktion
transformgeben, die ein Mensch-Objekt konsumiert und ein Wolfobjekt produziert (bzw. auch anders herum).
-
knivil schrieb:
von Object zu Chicken bzw zu Human
Wann bitte werden denn Huehner zu Menschen. Ok, es gibt Werwoelfe. Aber sie verwandeln sich, d.h. es sollte eine Funktion
transformgeben, die ein Mensch-Objekt konsumiert und ein Wolfobjekt produziert (bzw. auch anders herum).Vorausgesetzt die Identität des Menschen ist wichtig, wäre das wohl eher was für das State Pattern.

-
Das state pattern kannte ich noch nicht!
is ein guter tipp, auf den man eventuell zurück greifen kann.knivil schrieb:
[...]Aber sie verwandeln sich, d.h. es sollte eine Funktion
transformgeben, die ein Mensch-Objekt konsumiert und ein Wolfobjekt produziert (bzw. auch anders herum).Danke für den Hinweis. Manchmal sieht man den Wald vor lauter Bäumen nicht. So reicht doch ein Konstruktor in Chicken aus, der ein Object erwartet. (Alternativ kann man das ja auch in einer Methode transform einbauen).
Danke für den Hinweis!
#include <iostream> class Object { public: Object():member(4) { } virtual ~Object() { } protected: int member; }; class Creature : public Object { public: Creature(const Object& o) : Object(o) { } virtual void SayHello() const = 0; }; class Chicken : public Creature { public: Chicken(const Object& o) : Creature(o) { } static Chicken* transform(const Object& o) { return new Chicken(o); } void SayHello() const ; }; int main() { Object o; Chicken cicken(o); //alternativ: Chicken::transform(o); cicken.SayHello(); return 0; }