- Ja, sie sind gleich. Die abgeleitete Klasse, die etwas nicht als virtuell deklariert, hindert es nicht daran, virtuell zu sein. Tatsächlich gibt es keine Möglichkeit, zu verhindern, dass eine Methode (einschließlich Destruktor) in einer abgeleiteten Klasse virtuell ist, wenn sie in einer Basisklasse virtuell war. In> = C ++ 11 können Sie
final
verhindern, dass es in abgeleiteten Klassen überschrieben wird, aber das verhindert nicht, dass es virtuell ist.
- Ja, ein Destruktor in einer abgeleiteten Klasse kann weggelassen werden, wenn er nichts zu tun hat. Und es spielt keine Rolle, ob es virtuell ist oder nicht.
- Ich würde es wenn möglich weglassen. Und ich verwende das
virtual
Schlüsselwort aus Gründen der Klarheit immer wieder für virtuelle Funktionen in abgeleiteten Klassen. Die Benutzer sollten nicht die gesamte Vererbungshierarchie nach oben gehen müssen, um herauszufinden, dass eine Funktion virtuell ist. Wenn Ihre Klasse kopierbar oder verschiebbar ist, ohne dass Sie Ihre eigenen Kopier- oder Verschiebungskonstruktoren deklarieren müssen, werden Sie durch Deklarieren eines Destruktors jeglicher Art (auch wenn Sie ihn als definieren default
) gezwungen, die Kopier- und Verschiebungskonstruktoren und Zuweisungsoperatoren zu deklarieren, wenn Sie möchten Sie als Compiler werden sie nicht mehr für Sie eingeben.
Als kleiner Punkt für Punkt 3. In Kommentaren wurde darauf hingewiesen, dass der Compiler, wenn ein Destruktor nicht deklariert ist, einen Standard generiert (der immer noch virtuell ist). Und diese Standardeinstellung ist eine Inline-Funktion.
Inline-Funktionen setzen möglicherweise mehr Ihres Programms Änderungen in anderen Teilen Ihres Programms aus und machen die Binärkompatibilität für gemeinsam genutzte Bibliotheken schwierig. Außerdem kann die erhöhte Kopplung angesichts bestimmter Arten von Änderungen zu einer starken Neukompilierung führen. Wenn Sie beispielsweise entscheiden, dass Sie wirklich eine Implementierung für Ihren virtuellen Destruktor wünschen, muss jeder Code, der ihn aufgerufen hat, neu kompiliert werden. Wenn Sie es im Klassenkörper deklariert und dann in einer .cpp
Datei als leer definiert hätten, könnten Sie es problemlos ändern, ohne es neu zu kompilieren.
Meine persönliche Entscheidung wäre immer noch, es wegzulassen, wenn es möglich ist. Meiner Meinung nach ist der Code unübersichtlich, und der Compiler kann manchmal mit einer Standardimplementierung etwas effizienter arbeiten als mit einer leeren. Aber es gibt Einschränkungen, unter denen Sie möglicherweise stehen, die dies zu einer schlechten Wahl machen.
quelle
final
.Eine virtuelle Mitgliedsfunktion macht implizit jede Überladung dieser Funktion virtuell.
Das virtuelle in 1) ist also "optional", der virtuelle Basisklassendestruktor macht alle untergeordneten Destruktoren auch virtuell.
quelle
1 / Ja 2 / Ja, es wird vom Compiler generiert. 3 / Die Wahl, ob es als virtuell deklariert werden soll oder nicht, sollte Ihrer Konvention für überschriebene virtuelle Mitglieder entsprechen. IMHO, es gibt gute Argumente in beide Richtungen. Wählen Sie einfach eines aus und folgen Sie ihm.
Ich würde es wenn möglich weglassen, aber eines kann Sie dazu veranlassen, es zu deklarieren: Wenn Sie das vom Compiler generierte verwenden, ist es implizit inline. Es gibt Zeiten, in denen Sie Inline-Mitglieder vermeiden möchten (z. B. dynamische Bibliotheken).
quelle
Virtuelle Funktionen werden implizit überschrieben. Wenn die Methode einer untergeordneten Klasse mit der Methodensignatur der virtuellen Funktion einer Basisklasse übereinstimmt, wird sie überschrieben. Dies ist leicht zu verwirren und möglicherweise bricht während Refactoring, so gibt es
override
undfinal
Schlüsselwörter , da C ++ 11 explizit dieses Verhalten zu markieren. Es gibt entsprechende Warnungen, die das stille Verhalten beispielsweise-Wsuggest-override
in GCC verbieten .Es gibt eine verwandte Frage für
override
undfinal
Schlüsselwörter zu SO: Ist das Schlüsselwort 'override' nur eine Überprüfung für eine überschriebene virtuelle Methode? .Und die Dokumentation in der CPP-Referenz https://en.cppreference.com/w/cpp/language/override
Ob das
override
Schlüsselwort mit den Destruktoren verwendet werden soll, ist noch umstritten. Siehe zum Beispiel die Diskussion in dieser verwandten SO-Frage: Standardüberschreibung des virtuellen Destruktors Das Problem ist, dass sich die Semantik des virtuellen Destruktors von normalen Funktionen unterscheidet. Destruktoren sind verkettet, daher werden alle Basisklassen-Destruktoren nach Kind eins aufgerufen. Im Falle einer regulären Methodenbasis werden Implementierungen der überschriebenen Methode jedoch nicht standardmäßig aufgerufen. Sie können bei Bedarf manuell aufgerufen werden.quelle