web-dev-qa-db-fra.com

virtuel? passer outre? ou les deux? C ++

au cours des dernières semaines, quelque chose blesse mon cerveau au sujet du virtuel et du surpassement. J'ai appris que lorsque vous effectuez un héritage avec une fonction virtuelle, vous devez ajouter virtual pour que le compilateur sache qu'il recherche la bonne fonction. Par la suite, j'ai également appris que c ++ 11 comportait un nouveau mot-clé - override. Maintenant je suis un peu confus; Dois-je utiliser à la fois des mots-clés virtuels et des mots-clés de substitution dans mon programme, ou vaut-il mieux n'en utiliser qu'un seul?

Pour expliquer moi-même - exemples de code de ce que je veux dire:

class Base
{
public:
    virtual void print() const = 0;
    virtual void printthat() const = 0;
    virtual void printit() const = 0;
};

class inhert : public Base
{
public:
    // only virtual keyword for overriding.
    virtual void print() const {}

    // only override keyword for overriding.
    void printthat() const override {}

    // using both virtual and override keywords for overriding.
    virtual void printit() const override {}
};

Quelle est la meilleure méthode?

74
Daniel

Lorsque vous substituez une fonction, vous n'avez techniquement pas besoin d'écrire ni virtual ni override.

La déclaration de classe de base d'origine nécessite le mot clé virtual pour le marquer comme virtuel.

Dans la classe dérivée, la fonction est virtuelle, le type ¹same étant la fonction de classe de base.

Cependant, un override peut aider à éviter les bogues en produisant une erreur de compilation lorsque le remplacement prévu ne constitue techniquement pas un remplacement. Par exemple. que le type de fonction ne correspond pas exactement à la fonction de classe de base. Ou qu'une maintenance de la classe de base modifie le type de cette fonction, par ex. ajouter un argument par défaut.

De la même manière, un mot clé virtual dans la classe dérivée peut rendre un tel bogue plus subtil en s'assurant que la fonction est toujours virtuelle dans les autres classes dérivées.

Donc, le conseil général est,

  • Utilisez virtual pour la déclaration de fonction de classe de base.
    C'est techniquement nécessaire.

  • Utilisez override (uniquement) pour le remplacement d'une classe dérivée.
    Cela facilite la maintenance.

Exemple:

struct Base { virtual void foo() {} };
struct Derived: Base { void foo() override {} };

Notes:
¹ C++ prend en charge les résultats de pointeur et de référence bruts covariants. Avec la covariance, le type de substitution n'est pas exactement le même. Il a juste un type compatible.

118