2017-09-27 15 views
41

Par exemple:Est-il utile d'utiliser `override` pour remplacer une fonction virtuelle pure?

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

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

D'après ce que je lis, le mot-clé override est utilisé pour vous assurer que nous avons la signature correcte dans la fonction que nous prépondérants, et il semble être son utilisation seulement.

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). Donc, est-il utile d'ajouter override à la fin de la déclaration Derived::my_function()?

+4

Notez que l'abstrait * se propage *. Si vous fournissez la mauvaise signature dans la classe 'Derived', la classe' Derived' devient également abstraite. Cela pourrait ne pas être détecté au bon endroit sans le mot clé 'override'. –

+4

Il garantit que si la classe de base change de manière incompatible avec l'assertion 'override', votre code ne sera pas compilé. – EJP

+1

"Penning programmes pédagogiques délibérément propage des pratiques de programmation préférées" - T.J.Elgan – coderatchet

Répondre

67

However, in the case of a pure virtual function, the compiler would throw an error if we used an incorrect signature in the Derived class

Non, ce compile:

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

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

Bien que cela ne fait pas:

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

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

error: void Derived::my_function(int) marked override , but does not override


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

+0

Vous pourriez ajouter un bogue d'exécution avec une autre classe et implémenter 'Base :: my_function' tout en le laissant pur virtuel. – Yakk

+3

attendez donc il y a un point? Vous continuez à parler de comment c'est utile, mais commencez avec juste "non". – snb

+10

Le "Non" est en réponse à l'affirmation que le compilateur génère une erreur. –

30

Oui, c'est une bonne idée d'utiliser systématiquement le mot-clé override en tant que pratique défensive. Envisager une refonte lorsque l'auteur de la Base décide que my_function ne devrait plus être un virtuel pur, et aussi qu'il devrait prendre un nouveau paramètre. Avec override en place, le compilateur va attraper ce problème; sans override votre classe Derived continuerait à compiler.

7

Oui !!

Il améliore la clarté du code: override mot-clé empêche l'ambiguïté et de transmettre son sens de passer outre sa méthode de classe de base.

possible l'utilisation non intentionnelle Prévient: À l'avenir, si la signature de la méthode de classe de base de changement (ici virtual), il forcer la classe derive de changer en conséquence. (avec erreur de compilation). Sinon (sans mot-clé override), il pourrait être considéré method overload, ce qui n'est pas prévu.

+0

il ne serait pas la méthode de surcharge en raison de se cacher normalement, si – RiaD

3

Habituellement, ne pas déranger avec override déplace juste une erreur autour. Je trouve l'emplacement où vous obtenez le mieux l'erreur - au moment où vous définissez la méthode qui ne peut pas remplacer, au lieu de lorsque vous instancier la classe. Mais, il existe un moyen pour cela de se protéger contre un bug 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 de chaque foo appeler son parent foo.Mais parce que Derived::foo ne remplace pas la même signature que Base::foo, il n'est pas appelé.

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

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