Pure virtuelle Methode in abstrakter Klasse aufrufen???
-
Ich bin gestern abend auf folgendes gestossen, was mich doch sehr verwundert hat. Ich habe eine abstrakte Klasse, und wollte in einer ihrer implementierten Methoden eine pure virtuelle Methode aufrufen. Der Compiler lässt das auch durch gehen. Der Linker meckert aber, das die Implementierung fehlt. Irgendwie logisch für den Linker. Aber andererseits hat der Compiler doch auch Recht.
Im Stroustrup konnte ich kein ähnliches Beispiel finden. Weiß jemand ob mein Linker oder mein Compiler hier falsch arbeitet? (habe MSVC7.1) Ist es legaler C++ Code?
Beispielcode:
class A { public: A() { create(); // Compiler: OK. Linker: meckert das A::create() nicht da ist... } virtual void create() = 0; }; class B : public A { public: B() : A() { } virtual void create() { // implementierung } }; int main() { B b; }
-
Hi,
wenn ich mich recht entsinne, wird "die vtable erst später gefüllt", weswegen von Aufrufen virtueller Funktionen im Konstruktor abgeraten wird .... habe allerdings gerade keine Quelle dafür.
Gruß,
Simon2.
-
Hallo
Im Konstruktor von A ist die Instanz noch ein reines A, auch wenn der Konstruktor von dem Konstruktor von B aufgerufen wird. Das betrifft vor allem die virtuellen Funktionen. Im Konstruktor von A kann also niemals die Ableitungen von B aufgerufen werden.
Das das erst der Linker merkt, ist schade... aber besser als wenn die Funktion nicht abstrakt wäre und das Programm ein seltsames unerwartetes Verhalten zeigt, weil nicht die Methode aufgerufen wird wie erwartet.bis bald
akari
-
Schön dass es der Linker überhaupt merkt. Ich habe diese Lektion durch einen Programmabsturz gelernt

Also:
Niemals rein-virtuelle Methoden in Konstruktoren aufrufen. Überhaupt niemals virtuelle Methoden in Konstruktoren aufrufen (es seidenn man weiss und erwartet, dass die eigene Implementierung und nicht die der abgeleiteten Klasse durchlaufen wird)
-
Mann seid ihr schnell - ich war noch beim schreiben der Antwort

Gruß
Tntnet
-
Aha! Danke! Wieder was gelernt. Habe es bisher nur im Ctor ausprobiert. Aber klingt am Ende auch logisch. Aber wäre es nicht sinnvoller, wenn gleich der Compiler anmeckern würde? Gut, dann ist wenigstens der Linker von MSVC7.1 gut.
Muß MS nur noch beim Compiler nachziehen.
-
Artchi schrieb:
Aha! Danke! Wieder was gelernt. Habe es bisher nur im Ctor ausprobiert. Aber klingt am Ende auch logisch. Aber wäre es nicht sinnvoller, wenn gleich der Compiler anmeckern würde? Gut, dann ist wenigstens der Linker von MSVC7.1 gut.
Muß MS nur noch beim Compiler nachziehen.Man kann das diagnostizieren, wenn der Aufruf im Konstruktor selbst stattfindet. Eine Menge Fälle werden aber so nicht erfasst:
struct T { T() { foo(); } void foo(); virtual void bar() = 0; }; void T::foo() { bar(); }Hier kann der Compiler erst erkennen, dass der Konstruktor von T kritisch ist, nachdem er T::foo (das irgendwo anders definiert wird - jedenfalls außerhalb des für die Diagnose sichtbaren Bereichs) gesehen hat. Noch schlimmer ist die Abwandlung
struct T { T() { foo(); } void foo(); virtual void bar() = 0 {} }; void T::foo() { bar(); }Hier wird auch der Linker keine Schwierigkeiten machen. Es bleibt aber Unsinn, so dass der Standard das aus gutem Grund undefiniert lässt.