Was ist das Gegenteil von c ++ 'override' / 'final' Spezifizierer?

8
  • In c ++ 11 schützt der override -Spezifikator davor, eine beabsichtigte virtuelle Basisfunktion zu überschreiben (weil die Signaturen nicht übereinstimmen).
  • Der final -Spezifikator schützt vor unbeabsichtigtem Überschreiben einer Funktion in einer abgeleiteten Klasse.

= & gt; Gibt es einen Bezeichner (etwas wie vielleicht first oder no_override ), das vor dem Überschreiben einer unbekannten Basisfunktion schützt?

Ich möchte einen Compilerfehler erhalten, wenn eine virtuelle Funktion zu einer Basisklasse mit derselben Signatur wie eine bereits vorhandene virtuelle Funktion in einer abgeleiteten Klasse hinzugefügt wurde.

EDIT 4 : Um diese Frage einfach zu halten und relevante Antworten zu erhalten, hier ist wieder das

ursprünglicher Pseudocode

  • Zusammenfassung class B : A hat private: virtual void fooHasBeenDone() = 0;
  • class C : B implementiert private: virtual void fooHasBeenDone() override { react(); }
  • Jetzt bekommt class A eine neue private: virtual void fooHasBeenDone();
  • Aber das neue A::foo könnte etwas anderes sein als das ursprüngliche B::foo .

und ein spezifisches Beispiel

  • abstract class B : A hat virtual void showPath() = 0; einen PainterPath
  • verwendet
  • class C : B implementiert virtual void showPath() override { mPath.setVisible(); }
  • Nun erhält class A eine neue virtual void showPath(); , was einen Dateipfad
  • bedeutet
  • Wenn A jetzt showPath () aufruft, zeigt B den painterPath anstelle eines Dateipfads.

Natürlich ist das falsch, und ich sollte dann B::showPath() in B::showPainterPath() umbenennen und auch B::showPath() override implementieren. Ich möchte nur vom Compiler informiert werden.

Hier ist ein kompilierendes reales Beispiel :

%Vor%

Führen Sie es aus und sehen Sie sich die Textausgabe an.

Als Referenz ein älteres Beispiel mit einem bestimmten Anwendungsfall (PainterPath-Instanz):

Ссылка (der Link ist möglicherweise abgelaufen)

    
Martin Hennings 29.07.2016, 10:23
quelle

4 Antworten

2

Diese Antwort ist Community-Wiki, weil es alle anderen Antworten kombiniert. Bitte upvote die spezifische Antwort, die für Sie hilfreich war, sowie diese.

  1. Nein, es gibt keinen Spezifizierer wie first oder no_override . (Antwort)
  2. Sie sollten das override Bezeichner so oft wie möglich.
    Qt hat ein Makro Q_DECL_OVERRIDE , das zu override erweitert wird, falls verfügbar.
    Falls nicht verfügbar, markieren Sie jede überschreibende Funktion mit einem Kommentar.
  3. Wenn Sie das tun, gibt es Compiler-Flags, die vor einem fehlenden override warnen:
    " Clang hat jetzt -Winconsistent-missing-override und neuere GCCs haben -Wsuggest-override . "
    Ich kenne keine VS2012-Flagge dafür. Fühlen Sie sich frei zu bearbeiten.
  4. Sie können das gewünschte Verhalten nachahmen, indem Sie ein "Geheimnis" hinzufügen, das die Basisklasse nicht kennen kann. (Antwort)
    Dies ist in sehr spezifischen Anwendungsfällen hilfreich, bricht jedoch im Allgemeinen das Konzept der Virtualität (siehe Kommentare zu den anderen Antworten).
  5. Wenn Sie die Basisklasse nicht besitzen und einen Konflikt haben (z. B. Compilerwarnung), müssen Sie Ihre virtuelle Funktion in allen abgeleiteten Klassen umbenennen.
  6. Wenn Sie die Basisklasse besitzen, können Sie vorübergehend einer neuen virtuellen Funktion final hinzufügen. (antworten)
    Nachdem der Code ohne Fehler kompiliert wurde, wissen Sie, dass in keiner abgeleiteten Klasse eine Funktion mit diesem Namen und dieser Signatur vorhanden ist, und Sie können final erneut entfernen.

... Ich denke, ich werde anfangen, erste virtuelle Funktionen als DECL_FIRST zu markieren. Vielleicht wird es in Zukunft eine compilerunabhängige Möglichkeit geben, dies zu überprüfen.

    
Martin 23.05.2017, 12:23
quelle
2

Die Möglichkeit von Spezifizierern wie first oder no_override ist nicht als solche vorhanden. Wahrscheinlich, weil es Verwirrung stiften kann. Es kann jedoch trivial erreicht werden, indem der Ansatz geändert wird.

Man sollte jede neue Methode in der Basisklasse mit final specifier hinzufügen. Dies wird dazu beitragen, den Compilerfehler für alle übereinstimmenden Signaturen zu erhalten. Dadurch werden die nachfolgenden abgeleiteten Klassenverfahrensignaturen automatisch als "erste" ihrer Art festgelegt. Später kann das Schlüsselwort final entfernt werden , da es nur für die "Überprüfung aus erster Hand" gedacht war.

Putting & amp; Das Entfernen des Schlüsselworts final nach der neu hinzugefügten Basismethode ähnelt analog dem Kompilieren der Binärdatei mit der Option debug ( g++ -g ), die Ihnen hilft, den Fehler zu beheben. In der Produktion wird die Debug-Option zur Optimierung entfernt.

Aus Ihrem Beispiel:

%Vor%

Nun fügen Sie versehentlich eine ähnliche Methode in A hinzu, die zu einem Fehler führt:

%Vor%

Also die Signaturen zwischen neuen A::showPath() & amp; bestehende B::showPath() müssen verhandelt werden & amp; Fahren Sie dann fort, indem Sie final specifier entfernen.

    
iammilind 29.07.2016 10:50
quelle
2

Nein, gibt es nicht.

Das Hinzufügen einer virtuellen Funktion zu einer Basisklasse mit der gleichen Signatur wie eine virtuelle Funktion in einer untergeordneten Klasse kann keine vorhandene Funktionalität nicht brechen, es sei denn, Sie fügen diese virtuelle hinzu Funktion wandelt die Basisklasse in einen polymorphen Typ um . Also in der Norm, es ist gutartig, und eine reinste würde argumentieren, Hinzufügen von Sprach-Features, um dagegen zu schützen wäre ziemlich sinnlos.

(Natürlich könnten Sie Ihre neue Funktion final nur markieren, um zu überprüfen, ob eine untergeordnete Klassenfunktion sie nicht überlisten wird.)

Ihre einzige Option besteht darin, Code-Analyse-Tools zu verwenden.

(Beachten Sie, dass VS2012 den C ++ 11-Standard nicht implementiert oder sogar behauptet, ihn zu implementieren, obwohl er einiges davon enthält.)

    
Bathsheba 29.07.2016 10:29
quelle
1

C ++ scheint solche Mittel nicht bereit zu stellen. Aber Sie können es wie folgt nachahmen:

%Vor%

Wenn Sie eine neue virtuelle Funktion einführen möchten, tun Sie es wie folgt:

%Vor%     
Leon 29.07.2016 10:36
quelle