dynamisches Binden mit Rückgabewert
-
Hallo, ich komme aus der Java-Welt und verzweifle grad ein bisschen an den Besonderheiten von C++ in Bezug auf dynamisches Binden. Folgendes Beispiel:
ich habe 2 Klassen:
class Base { public: Base(); ~Base(); virtual void draw(); } class Special : public Base { public: Special(); ~Special(); virtual void draw(); } Nun habe ich in einer anderen Klasse Foo die Methode: Base& Foo::makeBase() { Special s(); return s; }
Wenn ich jetzt einfach aufrufe
Base b = makeBase(); b.draw();
wird nicht etwa Special::draw() aufgerufen sondern Base::draw(). Warum wird nicht einfach Special::draw() aufgerufen, schliesslich erstellt mein makeBase doch ein Special? An irgendeiner Stelle wird also scheinbar ein impliziter Downcast vorgenommen, den ich aber gar nicht haben will. Ich will das ich je nach Implementierung von makeBase() mal das eine und mal das andere zurückbekomme, jedoch alle nur als Base behandle. Denn es wird später noch sehr viel mehr Ableitungen von Base geben und nur makeBase() soll wissen, was da zusammengebaut wird. Später sollen diverse unterschiedliche Sachen einfach nur durch Aufruf von draw() gezeichnet werden, egal was tatsächlich dahinter steckt. In Java und C# würde es so gehen, bei C++ scheinbar nicht. Was mach ich falsch? Wie bekomme ich es hin, das es trotzdem geht?
Viele Grüße
Marco
-
Einige Anmerkungen:
class Base { public: Base(); ~Base(); // Wenn du virtuelle Funktionen anbietest, sollte auch der Destruktor virtual sein virtual void draw(); }; // Strichpunkt hat gefehlt :P class Special : public Base { public: Special(); ~Special(); virtual void draw(); }; // ; hat gefehlt :P Base& Foo::makeBase() { Special s(); // Das ist eine lokale FUnktionsdeklaration! return s; // Das geht mit einem lokalen Objekt schief, denn was zurück gegeben wird ist eine Referenz auf ein temporäres Objekt! GIBT AUA! }
Base b = makeBase(); // b ist eine Kopie des von makeBase zurückgegebenen Objekts. b ist keine Referenz.. b.draw(); // der Compiler macht hier statisches Binden.
-
Dein Code kann eig. gar nicht mal compilieren.
Was du suchst sind Pointer bzw. dynamische Objekte.Special s(); erzeugt kein Objekt.
#include <iostream> class Base { public: virtual void draw() {std::cout << "BASE" << std::endl; } }; // <-- Strichpunkt beachten class Special : public Base { public: virtual void draw() {std::cout << "SPECIAL" << std::endl;} }; Base* makeBase() { Special * s = new Special; return s; } int main() { Base * b = makeBase(); b->draw(); delete b; }
Gibt bei mir "SPECIAL" aus
-
Wow, sehr cool, danke für die schnelle Hilfe!
Jetzt funktionierts wie gewünscht! Habs genauso gemacht, wie Paul Manns es gepostet hat.
Gott sei dank geht es so, hatte schon befürchtet ich muss mein Konzept umschmeißen.Vielen Dank!
-
Und um die Freigabe nicht zu vergessen kannst du std::auto_ptr verwenden.