Virtuelle Konstruktoren
-
Der Aufruf von c.create() ruft den Konstruktor von Beispiel oder einer davon abgeleiteten Klasse auf. BeispieClass ist nichts 'real existierendes' - es ist eine Metaklasse. Sie liegt quasi zwischen Klasse und Objekt und stellt eine Polymorphie für Klassen dar.
Der Übergabeparameter c (BeispielClass) kann jetzt eine Referenz auf die Klasse Beispiel sein - oder auch ein Referenz auf eine beliebige von Beispiel abgeleitete Klasse. Der Typ des Objekts, das durch c.create() erzeugt wird, wird erst durch den Parameter c selbst festgelegt. Das Wissen was man da konkrekt erzeugt hat man aber hier nicht.Gebrauchen kann man das z.B. für Typ-Bibliotheken. Angenommen, die Klasse Beispiel hat eine virtuelle Methode name, die in jeder abgeleiteten Klasse überschrieben wird. Dann würde der Aufruf von c.name die konkrete Methode der abgeleiteten Klasse aufrufen. Wir sind also in der Lage, Objekte zu erzeugen, von denen wir überhaupt nichts wissen (außer die Basisklasse natürlich). Es ist eine andere Möglichkeit, generischen Code zu schreiben. (Delphi kennt keine Templates)
-
Kann man Factories ziemlich einfach implementieren
man kann factories auch in ein objekt packen und hat damit soetwas ähnliches wie deine metaklasse.
class Base {}; class Derived : public Base {} class Factory { private: string name; public: Factory(string const& name) : name(name) {} Base* create() const { return some_factory(name); } }; void foo(Factory f) { Base* p=f.create(); } foo(Factory("Derived"));
sieht doch süß aus, oder?
klar, es ist nicht ganz so fein, weile eine factory nicht ganz so dynamisch ist -> aber mit templates lässt sich das ganze ja etwas verbessern:
class Base {}; class Derived : public Base {} class BaseFactory { public: virtual Base* create() const = 0; }; template<class Class> class Factory : public BaseFactory { public: Base* create() const { return new Class(); } }; void foo(BaseFactory const& f) { Base* p=f.create(); } foo(Factory<Derived>());
jetzt muss man nur auf die polymorphie achten, das lässt sich aber dadurch aushebeln, dass foo selber ein template wird:
template<class T> void foo(Factory<T> f) { Base* p=f.create(); }
doch was sehe ich da:
template<class T> void foo() { T p; }
süß
-
Monastero schrieb:
Offensichtlich will 7H3 N4C3R bei der Erstellung eines Objekts den genauen Konstruktortyp nicht auswählen. So nach der Art: "Ich weiß nicht, was für ein Objekttyp du bist, ich gebe dir aber ein paar Informationen und dann erstelle dich einfach selbst." Erscheint mir schon sinnvoll.
Mir auch, das hat aber nichts mit virtuell zu tun.
-
Bashar schrieb:
Monastero schrieb:
Offensichtlich will 7H3 N4C3R bei der Erstellung eines Objekts den genauen Konstruktortyp nicht auswählen. So nach der Art: "Ich weiß nicht, was für ein Objekttyp du bist, ich gebe dir aber ein paar Informationen und dann erstelle dich einfach selbst." Erscheint mir schon sinnvoll.
Mir auch, das hat aber nichts mit virtuell zu tun.
Warum hat das nichts mit virtuell zu tun?
Wenn eine Methode virtuell aufgerufen wird, bedeutet das für mich: "Ich will von Dir, dass Du mir eine bestimmte Sache ausführst, und ich weiß nicht, was für ein konkretes Ding mir diese Sache ausführt. Sorg einfach dafür, dass das richtige Ding diese Sache ausführt".
Und genauso verhält sich das mit virtuellen Konstruktoren: "Führe mir die Konstruktion eines Objektes aus, obwohl ich gar nicht den Typ kenne".
-
Monastero schrieb:
Und genauso verhält sich das mit virtuellen Konstruktoren: "Führe mir die Konstruktion eines Objektes aus, obwohl ich gar nicht den Typ kenne".
Nur läuft das nicht so. Weil du irgendwo diese Typinformationen herhaben musst. Bei virtuellen Methoden ist es ja klar: du hast das konkrete objekt auch wenn du den typ nicht kennst, das objekt selber weiss es aber.
aber wovon willst du ein objekt erstellen wenn du _nichts_ hast?
-
Shade Of Mine schrieb:
aber wovon willst du ein objekt erstellen wenn du _nichts_ hast?
Genau "das" ist eine Klassenreferenz
(die es in C++ aber wiederum nicht gibt)
-
7H3 N4C3R schrieb:
Genau "das" ist eine Klassenreferenz
(die es in C++ aber wiederum nicht gibt)
Hast du dir meinen Code angesehen?
Man kann in C++ mit template da problemlos herum kommen. Und kann unterstützt sowohl dynamische als auch statische polymorphie. mach das mal mit deinen klassenreferenzen
-
Natürlich habe ich mir deinen Code angesehen. Wie wäre eine "Code-Witz des Tages"-Rubrik?
Ich sage ja auch garnichts dagegen, dass es mit Templates nicht sicherlich ähnliche Muster zur Problemlösung gibt. Nur wenn man keine Templates hat, dann braucht man einen anderen Mechanismus zur generischen Programmierung. Und das sind z.B. Klassenreferezen.
Hmm... das ist jetzt mal Ironie... ich erkläre mir gerade die Antwort auf meine ursprüngliche Frage
Vielleicht gerade noch ein technischer Unterschied (ich sage mit Absicht nicht Vorteil oder Nachteil): Bei Templates wird der Code sooft übersetzt, wie er mit verschiedenen Typen instanziiert wird - bei Klassenreferenzen dagegen nur einmal.
-
Virtuelle Konstruktoren als solche sind technisch einfach nicht möglich, noch machen sie Sinn - wo willste denn die virtuelle Funktion hernehmen, wenn du keine Instanz hast, die den Pointer hält?
Entweder, du willst eigentlich Konstruktorvererbung, oder du willst Reflection, oder ich hab keine Ahnung, was du eigentlich meinst.
-
0xdeadbeef schrieb:
wo willste denn die virtuelle Funktion hernehmen, wenn du keine Instanz hast, die den Pointer hält?
Bitte erstmal von Anfang an lesen... Die virtuelle Funktion würde aus einer Klassenreferenz kommen. Da aber keine Klassenreferenzen unter C++, auch keine virtuellen Konstruktoren. Und keine Klassenreferenzen unter C++, weil auch alles ähnlich über Templates abbildbar. Ist mir inzwischen seit meiner ursprünglichen Frage auch klar geworden.