Ist das Schlüsselwort 'override' nur eine Überprüfung auf eine überschriebene virtuelle Methode?


226

Soweit ich weiß, die Einführung von override Schlüsselworts in C ++ 11 nichts anderes als eine Überprüfung, um sicherzustellen, dass die implementierte Funktion die Funktion overrideeiner virtualFunktion in der Basisklasse ist.

Ist es das?



13
Es ist jedoch keine doppelte Überprüfung. Es ist der einzige Scheck.
Nikos C.

13
Hey, Override ist KEIN Schlüsselwort, es ist eine Art Grammatikzucker. int override = 42; // OK
KAlO2

2
Es verbessert zusätzlich die Lesbarkeit und erklärt, dass die deklarierte Funktion überschrieben wird;)
mots_g

5
Also, äh ... Wann wird C ++ 11 Standard genug, dass sie anfangen, solche Dinge in meinem lokalen 4-Jahres-Unterricht zu unterrichten? Wann werden sie es wissen?!
Cinch

Antworten:


263

Das ist in der Tat die Idee. Der Punkt ist, dass Sie explizit angeben, was Sie meinen, damit ein ansonsten stiller Fehler diagnostiziert werden kann:

struct Base
{
    virtual int foo() const;
};

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};

Der obige Code wird kompiliert, ist aber möglicherweise nicht das, was Sie gemeint haben (beachten Sie das Fehlen const). Wenn Sie stattdessen sagten, virtual int foo() overridewürden Sie einen Compilerfehler erhalten, dass Ihre Funktion tatsächlich nichts überschreibt.


74
+1: Leider ist es ein bisschen wie ein roter Hering, wenn Leute vorschlagen, dass die neue overrideFunktion dies "behebt"; Sie müssen daran denken, es zu verwenden, genau wie Sie daran gedacht haben sollten, das zu schreiben const;)
Lightness Races in Orbit

Ich habe gerade festgestellt, dass explicitKlassendefinitionen es nicht in C ++ 11 geschafft haben. Huh.
Aschepler

1
@aschepler Und was würde eine explicitKlassendefinition tun? Ich habe noch nie davon gehört.
Christian Rau

18
@LightnessRacesinOrbit: Ja, es ist nicht narrensicher; Das Erinnern an eine allgemeine Regel (verrücktes Schreiben, overridewenn man es vorhat) ist jedoch wahrscheinlicher als das Erinnern an Eckfälle, dh es gibt keine Allgemeingültigkeit beim Kopieren von Funktionen verschiedener Prototypen, nur Unregelmäßigkeiten wie Fehlen constoder Schreiben charstatt intusw.
legends2k

1
@Light, der beste Anwendungsfall des overrideSpezifizierers wird in dieser Antwort erwähnt , die eher futuristisch als unmittelbar ist. Die Antwort legt nahe, dass Sie overridedie virtualMethode beibehalten. Wenn man in Zukunft fälschlicherweise die Signatur ändert, setzt ihre Nützlichkeit ein.
iammilind

35

Wikipedia-Zitat:

Die spezielle ID zum Überschreiben bedeutet, dass der Compiler die Basisklasse (n) überprüft, um festzustellen, ob es eine virtuelle Funktion mit genau dieser Signatur gibt. Wenn dies nicht der Fall ist, tritt ein Fehler beim Compiler auf.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

Bearbeiten (versucht die Antwort ein wenig zu verbessern):

Das Deklarieren einer Methode als "Überschreiben" bedeutet, dass diese Methode eine (virtuelle) Methode für die Basisklasse umschreiben soll . Die überschreibende Methode muss dieselbe Signatur haben (zumindest für die Eingabeparameter) wie die Methode, die neu geschrieben werden soll.

Warum ist das notwendig? Nun, die folgenden zwei häufigen Fehlerfälle werden verhindert:

  1. man tippt einen Typ in der neuen Methode falsch ein. Der Compiler, der nicht weiß, dass er beabsichtigt, eine vorherige Methode zu schreiben, fügt sie der Klasse einfach als neue Methode hinzu. Das Problem ist, dass die alte Methode noch vorhanden ist, die neue wird nur als Überladung hinzugefügt. In diesem Fall funktionieren alle Aufrufe der alten Methode wie zuvor, ohne dass sich das Verhalten ändert (was der eigentliche Zweck des Umschreibens gewesen wäre).

  2. man vergisst, die Methode in der Oberklasse als "virtuell" zu deklarieren, versucht aber dennoch, sie in einer Unterklasse neu zu schreiben. Obwohl dies anscheinend akzeptiert wird, ist das Verhalten nicht genau wie beabsichtigt: Die Methode ist nicht virtuell, sodass der Zugriff über Zeiger auf die Oberklasse den Aufruf der alten Methode (Oberklasse ') anstelle der neuen Methode (Unterklasse') beendet.

Das Hinzufügen von "Überschreiben" macht dies eindeutig deutlich: Dadurch teilt man dem Compiler mit, dass drei Dinge erwartet werden:

  1. In der Oberklasse gibt es eine gleichnamige Methode
  2. Diese Methode in der Oberklasse wird als "virtuell" deklariert (dh soll neu geschrieben werden).
  3. Die Methode in der Oberklasse hat dieselbe (Eingabe *) Signatur wie die Methode in der Unterklasse (die Umschreibemethode).

Wenn einer dieser Punkte falsch ist, wird ein Fehler gemeldet.

* Hinweis: Der Ausgabeparameter ist manchmal von einem anderen, aber verwandten Typ. Lesen Sie bei Interesse mehr über kovariante und kontravariante Transformationen.


31

Gefunden " Überschreiben " ist nützlich, wenn jemand die Signatur der virtuellen Methode der Basisklasse aktualisiert hat, z. B. einen optionalen Parameter hinzugefügt hat, aber vergessen hat, die Signatur der abgeleiteten Klassenmethode zu aktualisieren. In diesem Fall sind die Methoden zwischen der Basis und der abgeleiteten Klasse keine polymorphe Beziehung mehr. Ohne die Override-Deklaration ist es schwierig, diese Art von Fehler herauszufinden.


1
+1. Obwohl dies overrideeine gute Möglichkeit ist, solche Probleme zu entdecken, sollte auch eine gute Abdeckung durch Unit-Tests hilfreich sein.
Desillusioniert

1
Genau deshalb freue ich mich so über diesen neuen Spezifizierer. Das einzige Problem ist, dass diese Funktion bereits angewendet werden muss, um Fehler zu vermeiden, die durch Änderungen in Basisklassen verursacht werden. ;-)
Wolf


2

C ++ 17 Standardentwurf

Nachdem ich alle overrideTreffer des C ++ 17 N4659-Standardentwurfs durchgesehen habe, kann ich nur auf den overrideBezeichner verweisen :

5 Wenn eine virtuelle Funktion mit dem Virt-Specifier-Override markiert ist und eine Member-Funktion einer Basisklasse nicht überschreibt, ist das Programm fehlerhaft. [Beispiel:

struct B {
  virtual void f(int);
};

struct D : B {
  virtual void f(long) override; // error: wrong signature overriding B::f
  virtual void f(int) override;  // OK
}

- Beispiel beenden]

Daher denke ich, dass möglicherweise das Sprengen falscher Programme der einzige Effekt ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.