Ist es wichtig, eine Definition für eine virtuelle Funktion zu haben?
Betrachten Sie das folgende Beispielprogramm:
%Vor%Dies ergibt den Link-Fehler:
In der Funktion
base::base()
:: undefinierter Verweis aufvtable for base
Ich habe keine Definition für die virtuelle Funktion in der Basisklasse. Warum tritt dieser Fehler auf, obwohl ich die virtuelle Funktion nicht explizit aufgerufen habe?
Die interessante Sache, die ich finde, ist, dass, wenn ich ein Objekt der Klasse derived
nicht instanziiere, der Verbindungsfehler nicht mehr da ist. Warum ist das? Was hat Instanziierung mit dem obigen Linkfehler zu tun?
Der ISO C ++ Standard gibt an, dass alle virtuellen Methoden einer Klasse, die nicht rein virtuell sind, definiert werden müssen.
Referenz:
C ++ 03 Standard: 10.3 Virtuelle Funktionen [class.virtual]
Eine in einer Klasse deklarierte virtuelle Funktion soll in dieser Klasse definiert oder als rein (10.4) deklariert werden oder beides; aber keine Diagnose ist erforderlich (3.2).
Entweder sollten Sie die Funktion rein virtuell machen oder eine Definition dafür bereitstellen.
Wenn Sie gcc verwenden, können einige seltsame Fehler auftreten, wenn Sie dieser Standardspezifikation nicht folgen. Die gcc faq dokumentiert dies ebenfalls:
Der ISO C ++ Standard gibt an, dass alle virtuellen Methoden einer Klasse, die nicht rein virtuell sind, definiert sein müssen, aber keine Diagnose für Verstöße gegen diese Regel
[class.virtual]/8
erfordert. Basierend auf dieser Annahme gibt GCC nur die implizit definierten Konstruktoren, den Zuweisungsoperator, den Destruktor und die virtuelle Tabelle einer Klasse in der Übersetzungseinheit aus, die ihre erste derartige nicht inline-Methode definiert.Wenn Sie diese spezielle Methode nicht definieren, kann sich der Linker daher über das Fehlen von Definitionen für scheinbar nicht verwandte Symbole beschweren. Leider, um diese Fehlermeldung zu verbessern, ist es möglicherweise notwendig, den Linker zu ändern, und dies kann nicht immer gemacht werden.
Die Lösung besteht darin, sicherzustellen, dass alle virtuellen Methoden, die nicht rein sind, definiert sind. Beachten Sie, dass ein Destruktor auch dann definiert werden muss, wenn er als reines virtuelles
[class.dtor]/7
deklariert ist.
Sie müssen eine Implementierung einer virtuellen Funktion (mit ihrem Standardverhalten) bereitstellen, es sei denn, Sie definieren die Funktion als "rein virtuell".
So könnte Ihr Beispiel sein:
%Vor%oder
%Vor%Als Reaktion auf den Fehler bezüglich der vtable: Der virtuelle Befehl teilt in diesem Fall c ++ mit, eine virtuelle Tabelle der Methoden in der Basisklasse zu erzeugen. Auf diese Weise kann C ++ bei Verwendung von Polymorphie die virtuellen Klassen der Basisklasse durch die Methoden der abgeleiteten Klasse mit demselben Namen zur Laufzeit ersetzen. Dieser Fehler weist den Benutzer darauf hin, dass dieser Austausch nicht möglich ist. Um diesen Fehler zu beheben, müssen Sie entweder die Methode implementieren oder sie als rein virtuell festlegen, indem Sie am Ende der Definition "= 0" hinzufügen.
Als Reaktion auf die Änderungen: Wenn Sie das Objekt als Basisklasse instanziieren, erhalten Sie keinen Fehler, weil die Basisklasse nicht auf die virtuelle Tabelle zugreifen muss. Wenn Sie jedoch tatsächlich versuchen, diese Methode zu verwenden, sollten Sie einen Fehler erhalten, da keine Implementierung vorhanden ist. Mit anderen Worten, obwohl Sie ein Objekt der Basisklasse instanziieren können, ist es keine vollständige Klasse.
Ja, Sie würden einen Körper brauchen, aber vielleicht wird das, was Sie meinen, reine virtuelle Funktionen genannt, die keine Definition in der Basisklasse benötigen.
Die Syntax zum Definieren dieser lautet wie folgt:
%Vor%Tags und Links c++ virtual-functions undefined-reference