Le mot clé 'override' n'est-il qu'une vérification d'une méthode virtuelle surchargée?

226

Pour autant que je sache, l'introduction du overridemot - clé en C ++ 11 n'est rien de plus qu'une vérification pour s'assurer que la fonction en cours d'implémentation est l' overrideingénierie d'une virtualfonction dans la classe de base.

Est-ce que c'est ça?

aiao
la source
50
Oui.⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣
R. Martinho Fernandes
13
Ce n'est pas une double vérification cependant. C'est le seul chèque.
Nikos C.
13
hé, remplacer n'est PAS un mot-clé, c'est une sorte de sucre grammatical. int override = 42; // OK
KAlO2
2
Il améliore également la lisibilité en expliquant que la fonction déclarée est remplacée;)
mots_g
5
Alors, euh ... Quand le C ++ 11 deviendra-t-il suffisamment standard pour qu'ils commencent à enseigner des choses comme ça lors de mes 4 ans locaux? Quand sauront-ils?!
Cinch

Réponses:

263

Voilà bien l'idée. Le fait est que vous êtes explicite sur ce que vous voulez dire, afin qu'une erreur par ailleurs silencieuse puisse être diagnostiquée:

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

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

Le code ci-dessus se compile, mais n'est pas ce que vous avez pu vouloir dire (notez le manquant const). Si vous dites à la place, virtual int foo() overridevous obtiendrez une erreur de compilation que votre fonction ne remplace en fait rien.

Kerrek SB
la source
74
+1: Bien que, malheureusement, c'est un peu un hareng rouge lorsque les gens suggèrent que la nouvelle overridefonctionnalité "corrige" cela; vous devez vous rappeler de l'utiliser, tout comme vous auriez dû penser à écrire le const;)
Courses de légèreté en orbite
Je viens de réaliser que explicitles définitions de classe ne sont pas entrées dans C ++ 11. Huh.
aschepler
1
@aschepler Et que ferait une explicitdéfinition de classe? Je n'en ai jamais entendu parler.
Christian Rau
18
@LightnessRacesinOrbit: Oui, ce n'est pas infaillible; cependant, se souvenir d'une règle générale (d'écrire follement overridequand on a l'intention de le faire) est plus probable que de se souvenir des cas d'angle, c'est-à-dire qu'il n'y a pas de généralité dans les fonctions de copie de différents prototypes, seulement des irrégularités comme manquer constou écrire à la charplace int, etc.
legends2k
1
@Light, le meilleur cas d'utilisation de overridespécificateur est mentionné dans cette réponse , qui est plus futuriste qu'immédiate. La réponse suggère que, gardez le overrideavec la virtualméthode. À l'avenir, lorsque l'on change par erreur la signature, son utilité entre en jeu.
iammilind
35

Citation de Wikipedia:

L'identifiant spécial de remplacement signifie que le compilateur vérifiera la ou les classes de base pour voir s'il existe une fonction virtuelle avec cette signature exacte. Et s'il n'y en a pas, le compilateur sortira en erreur.

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

Modifier (en essayant d'améliorer un peu la réponse):

Déclarer une méthode comme "override" signifie que cette méthode est destinée à réécrire une méthode (virtuelle) sur la classe de base. La méthode prioritaire doit avoir la même signature (au moins pour les paramètres d'entrée) que la méthode qu'elle a l'intention de réécrire.

Pourquoi est-ce nécessaire? Eh bien, les deux cas d'erreur courants suivants sont évités:

  1. on tape mal un type dans la nouvelle méthode. Le compilateur, ignorant qu'il a l'intention d'écrire une méthode précédente, l'ajoute simplement à la classe en tant que nouvelle méthode. Le problème est que l'ancienne méthode est toujours là, la nouvelle est ajoutée juste comme une surcharge. Dans ce cas, tous les appels vers l'ancienne méthode fonctionneront comme avant, sans aucun changement de comportement (ce qui aurait été le but même de la réécriture).

  2. on oublie de déclarer la méthode dans la superclasse comme "virtuelle", mais tente toujours de la réécrire dans une sous-classe. Bien que cela soit apparemment accepté, le comportement ne sera pas exactement celui prévu: la méthode n'est pas virtuelle, donc l'accès via des pointeurs vers la superclasse finira par appeler l'ancienne méthode (superclasse ') au lieu de la nouvelle méthode (sous-classe').

L'ajout de "override" dissipe clairement cette ambiguïté: à travers cela, on dit au compilateur que trois choses sont attendues:

  1. il y a une méthode avec le même nom dans la superclasse
  2. cette méthode dans la superclasse est déclarée "virtuelle" (c'est-à-dire destinée à être réécrite)
  3. la méthode dans la superclasse a la même signature (entrée *) que la méthode dans la sous-classe (la méthode de réécriture)

Si l'un d'eux est faux, une erreur est signalée.

* remarque: le paramètre de sortie est parfois de type différent mais lié. Lisez à propos des transformations covariantes et contravariantes si vous êtes intéressé.

user1284631
la source
31

Un " remplacement " trouvé est utile lorsque quelqu'un met à jour la signature de la méthode virtuelle de la classe de base, comme l'ajout d'un paramètre facultatif, mais oublie de mettre à jour la signature de la méthode de classe dérivée. Dans ce cas, les méthodes entre la base et la classe dérivée ne sont plus des relations polymorphes. Sans la déclaration de remplacement, il est difficile de trouver ce type de bogue.

user3792211
la source
1
+1. Bien que ce overridesoit un excellent moyen de découvrir de tels problèmes, une bonne couverture des tests unitaires devrait également aider.
Désillusionné le
1
C'est exactement pourquoi je suis si enthousiasmé par ce nouveau spécificateur. Le seul problème est que cette fonctionnalité doit être déjà appliquée pour éviter les erreurs causées par des changements dans les classes de base. ;-)
Wolf
2

Projet standard C ++ 17

Après avoir parcouru tous les overridehits du projet standard C ++ 17 N4659 , la seule référence que je peux trouver à l' overrideidentifiant est:

5 Si une fonction virtuelle est marquée avec la substitution virt-specifier et ne remplace pas une fonction membre d'une classe de base, le programme est mal formé. [ Exemple:

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
}

- exemple de fin]

donc je pense que faire exploser de mauvais programmes est en fait le seul effet.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source