web-dev-qa-db-fra.com

Le mot clé 'override' est-il simplement une vérification d'une méthode virtuelle remplacée?

Autant que je sache, l'introduction du mot clé override dans C++ 11 n'est rien de plus qu'une vérification permettant de s'assurer que la fonction implémentée est le overrideing d'une fonction virtual dans la classe de base.

Est-ce que c'est ça?

190
aiao

C'est bien l'idée. Le fait est que vous êtes explicite sur ce que vous voulez dire, de sorte 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 est compilé, mais n’est pas ce que vous avez voulu dire (notez la variable const manquante). Si vous disiez plutôt virtual int foo() override, vous obtiendrez une erreur du compilateur indiquant que votre fonction ne remplace en réalité rien.

217
Kerrek SB

Citation Wikipedia:

L'identificateur spécial de substitution 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 se trompera.

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

Edit (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 de substitution 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 erreurs courantes suivantes sont évitées:

  1. l'un des types incorpore un type dans la nouvelle méthode. Le compilateur, ignorant qu'il a l'intention d'écrire une méthode précédente, l'a simplement ajoutée à 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 comme une surcharge. Dans ce cas, tous les appels vers l'ancienne méthode fonctionneront exactement 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 on essaie toujours de la réécrire dans une sous-classe. Bien que cela soit apparemment accepté, le comportement ne sera pas exactement comme prévu: la méthode n'est pas virtuelle, aussi l'accès via les pointeurs vers la superclasse se terminera par l'appel de l'ancienne méthode (superclass ') au lieu de la nouvelle (sous-classe').

Ajouter "override" élimine clairement toute ambiguïté: par ceci, on indique au compilateur que trois choses s’attendent:

  1. il existe une méthode du même nom dans la superclasse
  2. cette méthode dans la superclasse est déclarée comme "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 de ces éléments 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 cela vous intéresse.

30
user1284631

Trouvé " override " est utile lorsque quelqu'un a mis à jour la signature de méthode virtuelle de classe de base, tel que l'ajout d'un paramètre facultatif, mais oublié de mettre à jour la signature de 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 substitution, il est difficile de trouver ce type de bogue.

24
user3792211

Oui, c'est comme ça. C’est une vérification pour s’assurer que l’on n’essaye pas de dérogation et que l’on passe à travers une signature bâclée. Voici une page Wiki qui explique cela en détail et qui présente un court exemple illustratif:

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

5
RonaldBarzell

Projet de norme C++ 17

Après avoir examiné tous les hits override sur le brouillon standard C++ 17 N4659 , la seule référence que je puisse trouver à l'identificateur override est la suivante:

5 Si une fonction virtuelle est marquée avec le remplacement par virt-specifier et ne remplace pas une fonction membre d'un 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
}

- fin exemple]

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