Virtuelle Überlegungen in C ++

Sie müssen im Kopf, ein paar Dinge zu halten, wenn virtuelle Funktionen in C ++ verwenden. Zunächst statische Member-Funktionen können nicht virtuell deklariert werden. Da statische Member-Funktionen nicht mit einem Objekt aufgerufen werden, gibt es keine Laufzeitobjekt, auf dem eine verbindliche Entscheidung zu stützen.

Zweitens in dem Aufruf der Klassennamens erzwingt einen Anruf früh zu binden, ob die Funktion virtuell ist. Zum Beispiel ist der folgende Aufruf Base :: fn () denn das ist es, was der Programmierer angezeigt, auch wenn fn () erklärt virtuell:

Leere Test (Basis b) {b.Base :: fn () - // Dieser Aufruf ist nicht gebunden spät}

Schließlich können Konstrukteure nicht virtuell sein, weil es keine (abgeschlossen) Objekt verwenden, um die Art zu bestimmen. Zu der Zeit wird der Konstruktor aufgerufen, der Speicher, der das Objekt einnimmt, ist nur eine amorphe Masse. Es ist erst nach der Konstruktor beendet hat, dass das Objekt ein Mitglied der Klasse in gutem Ansehen.

Im Vergleich dazu sollte die destructor fast immer virtuell deklariert werden. Wenn nicht, laufen Sie Gefahr, nicht richtig, das Objekt zu zerstören, wie in der folgenden Umstand:

class Base {public: ~ Base () -} - Klasse SubClass: public Basis {public: ~ SubClass () -} - Leere finishWithObject (Basis * pHeapObject) {// ... arbeiten mit dem Objekt ... // jetzt Rückkehr es zu der heapdelete pHeapObject- // dies ruft ~ Base () egal} // der Laufzeittyp von // pHeapObject

Wenn der Zeiger übergeben finishWithObject () wirklich deutet auf eine Unterklasse, das Unterklasse destructor ist nicht richtig aufgerufen - weil der Destruktor nicht virtuell deklariert wurde, ist es immer früh gebunden. die destructor virtuellen Deklarieren löst das Problem.

Also, wenn Sie würde nicht den Destruktor virtuell deklarieren möchten? Es gibt nur einen Fall. Virtuelle Funktionen einführen ein # 147-little # 148- Overhead.

Genauer gesagt: Wenn der Programmierer die erste virtuelle Funktion in einer Klasse definiert, fügt C ++ eine zusätzliche, versteckte Zeiger - nicht ein Zeiger pro virtuelle Funktion, nur einen Zeiger, wenn die Klasse keine virtuellen Funktionen hat. Eine Klasse, die keine virtuellen Funktionen hat (und nicht erben keine virtuellen Funktionen von Basisklassen) nicht diesen Zeiger.

Nun wird ein Zeiger nicht viel zu sein, und es ist nicht, wenn die folgenden zwei Bedingungen erfüllt sind:

  • Die Klasse hat nicht viele Datenelemente (so dass ein Zeiger eine Menge darstellt im Vergleich zu dem, was schon da).

  • Sie beabsichtigen, viele Objekte dieser Klasse zu erstellen (sonst der Aufwand keinen Unterschied macht).

Wenn diese beiden Bedingungen erfüllt sind und die Klasse nicht bereits virtuelle Member-Funktionen, können Sie nicht den Destruktor virtuell deklarieren möchten.

Außer diesem einen Fall, erklären immer virtuell sein Destruktoren, auch wenn eine Klasse nicht subclassed ist (noch) nicht - man weiß ja nie, wenn jemand vorbeikommt und nutzen Sie Ihre Klasse als Basisklasse für ihre eigene. Wenn Sie nicht die destructor virtuellen erklären, erklären Sie dann die Klasse final (wenn Ihr Compiler diese Funktion unterstützt) und dokumentieren!

Menü