Wir haben ein spezielles Framework für Schnittstellen in unserem Projekt, und ein Teil der Anforderungen besteht darin, dass Klassen, die eine Schnittstelle darstellen, nur als virtuelle Basisklassen und nicht als nicht-virtuelle Klassen verwendet werden dürfen. Gibt es eine Möglichkeit, dies in Code zu erzwingen? Das heißt, einen Kompilierungsfehler erzeugen, wenn die Klasse von nicht virtuell abgeleitet ist.
Ich habe Zugriff auf C ++ 11, wie von VS 2010 implementiert: das bedeutet static_assert
, enable_if
und <type_traits>
sind verfügbar.
IMO, es gibt keine saubere und plattformunabhängige Lösung für dieses Problem.
Der beste Weg ist, manuell jede einzelne Vererbung in virtual
Vererbung zu ändern.
Um dies zu erreichen, ist es einfach (!), Die abgeleiteten Klassen Ihrer Schnittstelle (zB class Base
) zu identifizieren. Die folgenden Schritte können dafür ausgeführt werden:
class Base
als final
(c ++ 11); d.h. class Base final { ...
virtual
und kompilieren Sie den Code erfolgreich Dieser Prozess muss (leider) regelmäßig durchgeführt werden, wann immer Sie eine solche Überprüfung durchführen wollen.
Dies kann zum Zeitpunkt der Kompilierung überprüft werden. Der Schlüssel ist, wenn wir ein Rautenmuster haben:
Sie können D&
eindeutig auf A&
anwenden. Wenn die Vererbung jedoch nicht virtuell ist:
Die Besetzung würde mehrdeutig sein. Also lass uns versuchen, einen Diamanten zu machen!
%Vor% An diesem Punkt ist es nur ein weiterer void_t
-Style-Typ:
Wenn die Besetzung eindeutig ist, ist der Ausdruck in der Teilspezialisierung gültig, und diese Spezialisierung wird bevorzugt. Wenn der Cast zweideutig ist, haben wir einen Substitutionsfehler und landen am Primary. Beachten Sie, dass Base
hier nicht unbedingt virtual
-Memberfunktionen haben muss:
Und wenn es reine virtuelle Elementfunktionen hat, müssen wir sie nicht überschreiben, da wir niemals ein Objekt konstruieren.
%Vor% Natürlich, wenn Ihre Klasse final
markiert ist, wird dies überhaupt nicht funktionieren. Aber wenn es final
wäre, wäre es egal, welche Art von Vererbung es ohnehin hatte.
Interessantes Problem. Sie können sich dem gewünschten Ziel nähern, indem Sie die Interface-Klasse verbergen und eine konkrete Klasse offenlegen, die virtuell von der Schnittstelle erbt. Dies bringt natürlich einige Umwege und Unannehmlichkeiten mit sich, aber es kann an Ihre Bedürfnisse angepasst werden. Hier ist ein Beispiel:
%Vor% Es kann möglich sein, einen Namen mit decltype()
und as_interface()
zu rekonstruieren, der für die Vererbung geeignet sein könnte, aber die, die ich probiert habe, führten zu Compiler-Fehlern, die der Destruktor geschützt war. es ist zumindest relativ schwierig und könnte für Ihre Bedürfnisse ausreichen.
Tags und Links c++ c++11 virtual-inheritance typetraits static-assert