web-dev-qa-db-fra.com

Y a-t-il un intérêt à utiliser `override` lors de la substitution d'une fonction virtuelle pure?

Par exemple:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function() override;
};

D'après ce que j'ai lu, le mot clé override est utilisé pour s'assurer que nous avons la signature correcte dans la fonction que nous remplaçons, et il semble que ce soit sa seule utilisation.

Cependant, dans le cas d'une fonction virtuelle pure, le compilateur lancerait une erreur si nous utilisions une signature incorrecte dans la classe Derived (ou la classe Base, selon la façon dont on voit les choses). Alors, est-il utile d'ajouter override à la fin de la déclaration Derived::my_function()?

43
R2B2

Cependant, dans le cas d'une fonction virtuelle pure, le compilateur lancerait une erreur si nous utilisions une signature incorrecte dans la classe Derived

Non, cela compile:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function(int);
//                 ^^^ mistake!
};

Bien que cela ne:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function(int) override;
};

erreur: void Derived::my_function(int) marquée override, mais ne remplace pas


L'erreur dont vous parlez ne se produit que lorsque l'instanciation de Derived - override vous permet de détecter l'erreur plus tôt et rend la définition de Derived plus claire/plus lisible.

72
Vittorio Romeo

Oui, c'est une bonne idée d'utiliser le mot clé override de manière cohérente comme pratique défensive.

Envisagez une refonte lorsque l'auteur du Base décide que my_function ne devrait plus être un pur virtuel, et aussi qu'il devrait prendre un nouveau paramètre. Avec override en place, le compilateur détectera ce problème; sans override votre classe Derived continuerait de compiler.

31
dasblinkenlight

Oui !!

Il améliore la clarté du code: override le mot clé empêche l'ambiguïté et transmet sa signification de redéfinir sa méthode de classe de base.

Empêche une utilisation involontaire possible: À l'avenir, si la signature de la méthode de changement de classe de base (ici virtual), elle force la classe dérivée à changer en conséquence. (avec erreur de compilation). Sinon (sans mot clé override), il pourrait être considéré comme method overload, ce qui n'est pas prévu.

7
JharPaat

Habituellement, ne pas se soucier de override déplace simplement une erreur. Je trouve mieux l'emplacement où vous obtenez l'erreur - au point où vous définissez la méthode qui ne parvient pas à remplacer, plutôt que lorsque vous instanciez la classe.

Mais, il existe un moyen de se protéger contre un bogue d'exécution.

struct Base {
  virtual void foo(int x = 0) = 0;

  void foo(double d) {
      foo( (int)d );
  }
};
inline void Base::foo(int x) { std::cout << "Default foo(" << x << ")\n"; }

struct Derived:Base {
  using Base::foo;
  virtual void foo() { // oops, no int!
    std::cout << "Derived::foo()\n";
    Base::foo();
  }
};
struct Derived2:Derived {
  virtual void foo(int x=0) override {
    std::cout << "Derived2::foo()\n";
    Derived::foo(x);
  }
};

ici, nous avons l'intention pour chaque foo d'appeler son parent foo. Mais parce que Derived::foo Ne remplace pas la même signature que Base::foo, Il n'est pas invoqué.

Ajoutez override après foo() dans Derived et nous obtenons une erreur de compilation.

Et oui, j'ai implémenté la fonction virtuelle pure Base::foo.

3