In verschiedenen Erklärungen von C ++ 11% final
Schlüsselwort, ich sehe Beispiele wie diese.
Ist das wirklich eine nützliche Verwendung von final
? Warum würden Sie eine virtuelle Funktion in einer Basisklasse deklarieren (was bedeutet, dass sie in abgeleiteten Klassen sinnvollerweise außer Kraft gesetzt werden kann) und dann sofort als final
markieren (diese Implikation negieren)? Was ist der Nutzen von virtual void f() final
?
Ich kann den Wert der Markierung derived::f()
final statt base::f()
sehen. In diesem Fall hatte base::f()
vermutlich einen guten designbasierten Grund dafür, warum f()
virtuell sein sollte, und derived::f()
hat separat einen guten designbasierten Grund dafür, warum keine weiter abgeleitete Klasse ihre Implementierung außer Kraft setzen sollte.
Wenn Sie die Funktion nicht polymorph überschreiben möchten, warum lassen Sie nicht einfach das virtuelle Schlüsselwort weg? Natürlich können abgeleitete Klassen die Funktion immer noch nicht-polymorph überschreiben. Ist der Zweck von virtual void f() final
in der Basisklasse daher, base::f()
in irgendeiner Weise fest-nicht-überschreibbar zu machen - entweder als virtuelle oder nicht-virtuelle Funktion? Wenn dem so ist, dann scheint es ein bisschen bedauerlich, dass wir das virtual
-Schlüsselwort in diesem Fall nur hinzufügen müssen, um die Verwendung von final
zu ermöglichen. Ich würde denken, dass es dann legal sein sollte, auch nicht-virtuelle Funktionen als endgültig zu markieren.
Warum virtual void f() final
für eine Funktion verwenden, die aus einer Basisklasse stammt, wenn der Sinn von virtual
und der Sinn von final
zu widersprechen scheinen?
Ist es sinnvoll, eine Basisklassenfunktion sowohl als virtuell als auch als final zu markieren?
Ja, zumindest vorübergehend.
Ich fand mich in einer relativ großen und unbekannten existierenden C ++ Quellcode-Basis wieder. Ein Großteil des Codes wurde vor C ++ 11 geschrieben. Ich stellte fest, dass ich sicherstellen wollte, dass alle Überschreibungen einer virtuellen Funktion in einer Basisklasse mit override
markiert wurden. Der schwierige Teil ist das Auffinden all dieser Überschreibungen.
Ich habe die virtuelle Funktion in der Basisklasse mit final
markiert, und der Compiler hat mir schnell gezeigt, wo jeder einzelne Override deklariert wurde. Es war dann sehr einfach, die Overrides zu dekorieren, wie ich wollte, und das final
aus dem virtuellen in der Basisklasse zu entfernen.
Sie können es als virtual
markieren, um anzuzeigen, dass es in der Klasse, von der Sie übernommen werden, 'virtuell' ist (obwohl Sie dies nicht tun müssen) und markieren Sie final
, um anzugeben, dass keine Klasse abgeleitet wird von Ihrer Klasse kann es weiter überschreiben. Dies kann beispielsweise der Fall sein, wenn Sie eine abstrakte Basisklasse implementieren. Das ist C ++ 11, also ist es nicht nützlich; override
ist ein viel besseres Zeichen, da es vom Compiler erzwungen wird.
Eine andere Möglichkeit: Sie möchten, dass diese Methode nicht überschrieben wird, aber Sie möchten dies ohne Neukompilierung ändern können. Denken Sie daran, dass virtual
bedeutet, dass es sich in der virtuellen Tabelle befindet. auch wenn der Compiler sie nicht überschreiben lässt.
Ich denke, der Zweck des Beispiels, das Sie gezeigt haben, besteht darin, Prioritäten zwischen virtual
und final zu demonstrieren, und nicht mehr. Es ist eine minimale Verwendung von final
, keine sinnvolle.
Das Markieren einer nicht virtuellen Methode als final
macht keinen Sinn, da Sie sie sowieso nicht überschreiben können. Wenn der Compiler das Ausblenden verhindern soll, ist das ein völlig anderes Problem, das nichts mit der Methode final
zu tun hat. In gewissem Sinne sind nicht-virtuelle Methoden bereits endgültig, aber versteckt.
Die Alternative ist eine nicht-virtuelle Funktion. Aber nicht-virtuelle Funktion kann durch eine abgeleitete Klasse verborgen werden. Wenn Sie also verhindern wollen, dass eine Funktion ausgeblendet wird, kann sie als virtuelles Letztes angegeben werden.