J'ai une classe de base avec une fonction virtuelle et je souhaite remplacer cette fonction dans une classe dérivée. Existe-t-il un moyen de faire en sorte que le compilateur vérifie si la fonction que j'ai déclarée dans la classe dérivée remplace réellement une fonction dans la classe de base? Je voudrais ajouter une macro ou quelque chose qui garantit que je n'ai pas accidentellement déclaré une nouvelle fonction, au lieu de remplacer l'ancienne.
Prenons cet exemple:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Ici parent::handle_event()
est appelée à la place de child::handle_event()
, car la méthode de l'enfant manque la const
déclaration et déclare donc une nouvelle méthode. Cela peut également être une faute de frappe dans le nom de la fonction ou une différence mineure dans les types de paramètres. Cela peut également se produire facilement si l'interface de la classe de base change et que quelque part une classe dérivée n'a pas été mise à jour pour refléter le changement.
Existe-t-il un moyen d'éviter ce problème, puis-je dire au compilateur ou à un autre outil de vérifier cela pour moi? Des indicateurs de compilation utiles (de préférence pour g ++)? Comment évitez-vous ces problèmes?
Réponses:
Depuis g ++ 4.7, il comprend le nouveau
override
mot-clé C ++ 11 :la source
override
doit être utilisé dans la définition. Une implémentation en ligne est à la fois définition et implémentation, donc ça va.Quelque chose comme le
override
mot clé de C # ne fait pas partie de C ++.Dans gcc,
-Woverloaded-virtual
met en garde contre le masquage d'une fonction virtuelle de classe de base avec une fonction du même nom mais une signature suffisamment différente pour ne pas la remplacer. Cela ne vous protégera pas, cependant, de ne pas remplacer une fonction en raison d'une mauvaise orthographe du nom de la fonction elle-même.la source
override
mot clé en C ++; cela peut signifier que vous utilisez quelque chose qui peut compiler du code source C ++ invalide, cependant. ;)override
fonctionnalité de style C # ; J'ai rarement eu des problèmes avec les remplacements échoués et ils ont été relativement faciles à diagnostiquer et à résoudre. Je ne suis pas d'accord avec le fait que les utilisateurs de VC ++ devraient l'utiliser. Je préférerais que C ++ ressemble à C ++ sur toutes les plates-formes, même si un projet particulier n'a pas besoin d'être portable. Il convient de noter que C ++ 0x aura[[base_check]]
,[[override]]
et les[[hiding]]
attributs de sorte que vous pouvez opter pour passer outre vérifier si on le souhaite.override
mot-clé, il semble que ce soit le cas . Eh bien, pas un mot clé correct mais un identifiant spécial en C ++ 11. Microsoft a suffisamment insisté pour en faire un cas particulier et pour suivre le format général des attributs etoverride
en faire la norme :)Pour autant que je sache, ne pouvez-vous pas simplement le rendre abstrait?
Je pensais avoir lu sur www.parashift.com que vous pouvez réellement implémenter une méthode abstraite. Ce qui a du sens pour moi personnellement, la seule chose qu'il fait est de forcer les sous-classes à l'implémenter, personne n'a dit quoi que ce soit à propos de ne pas être autorisé à avoir une implémentation elle-même.
la source
BaseClass::method()
) d'être appelée dans l'implémentation dérivée (par exempleDerivedClass::method()
), par exemple pour une valeur par défaut.Dans MSVC, vous pouvez utiliser le
override
mot clé CLR même si vous ne compilez pas pour CLR.Dans g ++, il n'y a pas de moyen direct d'appliquer cela dans tous les cas; d'autres personnes ont donné de bonnes réponses sur la façon de détecter les différences de signature en utilisant
-Woverloaded-virtual
. Dans une version future, quelqu'un pourrait ajouter une syntaxe similaire__attribute__ ((override))
ou l'équivalent en utilisant la syntaxe C ++ 0x.la source
Dans MSVC ++, vous pouvez utiliser le mot clé
override
override
fonctionne à la fois pour le code natif et CLR dans MSVC ++.la source
Rendez la fonction abstraite, de sorte que les classes dérivées n'aient pas d'autre choix que de la remplacer.
@Ray Votre code n'est pas valide.
Les fonctions abstraites ne peuvent pas avoir de corps définis en ligne. Il doit être modifié pour devenir
la source
Je suggérerais un léger changement dans votre logique. Cela peut fonctionner ou non, selon ce que vous devez accomplir.
handle_event () peut toujours faire le "code par défaut ennuyeux" mais au lieu d'être virtuel, au point où vous voulez qu'il fasse le "nouveau code passionnant", demandez à la classe de base d'appeler une méthode abstraite (c'est-à-dire qu'il faut remplacer la méthode) qui sera fourni par votre classe descendante.
EDIT: Et si vous décidez plus tard que certaines de vos classes descendantes n'ont pas besoin de fournir un "nouveau code passionnant" alors vous pouvez changer l'abstrait en virtuel et fournir une implémentation de classe de base vide de cette fonctionnalité "insérée".
la source
Votre compilateur peut avoir un avertissement qu'il peut générer si une fonction de classe de base est masquée. Si c'est le cas, activez-le. Cela attrapera les conflits const et les différences dans les listes de paramètres. Malheureusement, cela ne révélera pas une erreur d'orthographe.
Par exemple, il s'agit d'avertissement C4263 dans Microsoft Visual C ++.
la source
override
Mot clé C ++ 11 lorsqu'il est utilisé avec la déclaration de fonction à l'intérieur de la classe dérivée, il force le compilateur à vérifier que la fonction déclarée remplace en fait une fonction de classe de base. Sinon, le compilateur lèvera une erreur.Par conséquent, vous pouvez utiliser un
override
spécificateur pour assurer un polymorphisme dynamique (remplacement de fonction).la source