Vritual Methode und call by value
-
Hallo,
folgendes
#include <cstdlib> #include <iostream> using namespace std; class A { public: virtual void call() { cout << "Call A" << endl; } }; class B : public A { public: virtual void call() { cout << "Call B" << endl; A::call (); } }; class Container { A value; public: Container(const A& a) : value(a) {} void callValue() { value.call (); } }; /* * */ int main (int argc, char** argv) { B b; b.call (); cout << ".................." << endl; A& a = b; a.call (); cout << ".................." << endl; Container c(b); c.callValue (); }Ausgabe:
Call B Call A .................. Call B Call A .................. Call AWieso wird beim dritten mal nur die Methode der Klasse A aufgerufen. Ich kann mir das nicht erklären.
g++ --version g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5Danke, Thomas
-
Im Container-Konstruktor kopierst du das den Parameter in das A-Objekt "value" - dabei gehen auch alle Eigenschaften der abgeleiteten Klassen verloren. Wenn du Polymorphie nutzen willst, mußt du im Container eine Referenz oder einen Zeiger verwenden.
-
Siehe dafür auch "Object Slicing" Problem.
-
CStoll schrieb:
... Wenn du Polymorphie nutzen willst, mußt du im Container eine Referenz oder einen Zeiger verwenden.
Ich denke ich kenne die Antwort, aber dennoch ...
Ich benutze also die Variable A& value in der Klasse Container.Container abc() { B b; Container c(b); return c; } void test() { Container con = abc(); // .... con.callValue(); }Beim verlassen von abc() wird b zerstört und der Speicher freigegeben. Ist der Wert der Variable value im Container noch gültig? Oder ist es wie bei Zeigern, dass die Referenz nun auf einen freigegeben Speicher zeigt?
-
Siassei schrieb:
Ist der Wert der Variable value im Container noch gültig?
Ja, denn oben hast du in Zeile 33 eine Kopie gemacht.
Oder ist es wie bei Zeigern, dass die Referenz nun auf einen freigegeben Speicher zeigt?
Das kann schon passieren, wenn du Referenzen auf lokale Objekte zurück gibst. Das ist jedoch meistens recht leicht zu diagnostizieren für den Compiler, wenn du Warnungen aktivierst.
-
Siassei schrieb:
CStoll schrieb:
... Wenn du Polymorphie nutzen willst, mußt du im Container eine Referenz oder einen Zeiger verwenden.
Ich denke ich kenne die Antwort, aber dennoch ...
Ich benutze also die Variable A& value in der Klasse Container.Container abc() { B b; Container c(b); return c; } void test() { Container con = abc(); // .... con.callValue(); }Wenn du Container so verwendest wie in deinem Eröffnungsbeitrag verwendest, hast du im Container eine Kopie des lokalen Objekts in c - diese wird nach dem Verlassen der Funktion in con kopiert.
Mit der Anpassung "A**&** value;" hättest du ein Problem, weil dein Container eine Referenz auf etwas aufhebt, was irgendwann mal eine gültige Variable war (was inzwischen dort steht, weiß vermutlich nichtmal dein Compiler).
-
CStoll schrieb:
Mit der Anpassung "A**&** value;" hättest du ein Problem, weil dein Container eine Referenz auf etwas aufhebt, was irgendwann mal eine gültige Variable war (was inzwischen dort steht, weiß vermutlich nichtmal dein Compiler).
Danke.