Wenn ich eine Basisklasse deklariere, sollte ich alle darin enthaltenen Funktionen als virtuell deklarieren, oder sollte ich eine Menge virtueller Funktionen und eine Menge nicht virtueller Funktionen haben, von denen ich sicher bin, dass sie nicht vererbt werden? / p>
Eine Funktion muss nur virtuell sein, wenn eine abgeleitete Klasse diese Funktion auf andere Weise implementiert.
Zum Beispiel:
%Vor%Als Ergebnis würde ich die Seite, die nichts virtuell hat, fälschen, wenn Sie nicht im Voraus wissen, dass Sie beabsichtigen, es zu überschreiben, oder bis Sie feststellen, dass Sie das Verhalten benötigen. Die einzige Ausnahme ist der Destruktor, für den fast immer der Fall ist, dass er in einer Basisklasse virtuell sein soll.
Sie sollten nur Funktionen machen, die Sie beabsichtigen, virtuell zu überschreiben. Eine Methode virtuell zu machen ist nicht frei in Bezug auf Wartung und Leistung (Wartung ist das viel größere Problem IMHO).
Sobald eine Methode virtuell ist, wird es schwieriger, über irgendeinen Code nachzudenken, der diese Methode verwendet. Anstatt zu überlegen, was ein Methodenaufruf tun würde, müssen Sie überlegen, welche N-Methodenaufrufe in diesem Szenario ausgeführt würden. N gibt die Anzahl der Unterklassen an, die diese Methode überschreiben.
Die einzige Ausnahme von dieser Regel sind Destruktoren. Sie sollten in jeder Klasse virtuell sein, von der abgeleitet werden soll. Nur so kann sichergestellt werden, dass der richtige Destruktor während der Freigabe aufgerufen wird.
Das nicht-virtuelle Schnittstellen-Idiom (C ++ Coding Standards, Element 39) besagt, dass eine Basisklasse über nicht virtuelle Schnittstellenmethoden verfügen sollte, die es der Basisklasse ermöglichen, Invarianten zu garantieren, und nicht-öffentliche virtuelle Methoden zur Anpassung des Basisklassenverhaltens durch abgeleitete Klassen. Die nicht virtuellen Schnittstellenmethoden rufen die virtuellen Methoden auf, um das überschreibbare Verhalten bereitzustellen.
Ich tendiere dazu, nur die Dinge virtuell übersteuerbar zu machen. Wenn meine anfänglichen Annahmen über das, was ich außer Kraft setzen möchte, falsch sind, gehe ich zurück und ändere die Basisklasse.
Oh, und natürlich machen Sie Ihren Destruktor immer virtuell, wenn Sie an etwas arbeiten, von dem er geerbt wird.
Wenn Sie eine Basisklasse erstellen (Sie sind sicher, dass jemand die Klasse ableitet), können Sie folgende Dinge tun:
Der Compiler würde nicht wissen, welcher Code tatsächlich ausgeführt wird, wenn der Zeiger des Basistyps eine virtuelle Funktion aufruft. Daher muss der tatsächliche Codeabschnitt, der ausgeführt werden soll, zur Laufzeit ausgewertet werden, abhängig davon, auf welches Objekt der Basisklassenzeiger zeigt. Vermeiden Sie daher die Verwendung virtueller Funktionen, wenn die Funktion in einer geerbten Klasse nicht überschrieben werden soll.
TLDR-Version: "Sie sollten eine Reihe von virtuellen Funktionen und eine Reihe von nicht-virtuellen Funktionen haben, von denen Sie sicher sind, dass sie nicht vererbt werden." Weil virtuelle Funktionen zur Laufzeit eine Leistungsminderung verursachen.
Die Schnittstellenfunktionen sollten im Allgemeinen virtuell sein. Funktionen, die feste Funktionalität bieten, sollten nicht.
Warum erklären Sie etwas virtuell, bis Sie es wirklich überschreiben? Ich glaube, es geht nicht darum, sicher zu sein oder nicht. Befolgen Sie die Fakten: Wird es irgendwo überschrieben? Nein? Dann muss es nicht virtuell sein.
Tags und Links c++