Est-il possible d'empêcher une méthode d'être redéfinie dans les sous-classes?
Est-ce que quelqu'un connaît une fonctionnalité ou une technique de langage en C++ pour empêcher une classe enfant de surfer sur une méthode particulière dans la classe parent?
class Base {
public:
bool someGuaranteedResult() { return true; }
};
class Child : public Base {
public:
bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};
Même si ce n'est pas Virtuel, cela est toujours autorisé (au moins dans le compilateur Metrowerks que j'utilise), tout ce que vous obtenez est un avertissement de compilation sur le masquage de la fonction héritée Non virtuelle X.
14 réponses
Quelques idées:
- rendez votre fonction privée.
- Ne rendez pas votre fonction virtuelle. Cela n'empêche pas réellement la fonction d'être ombragée par une autre définition.
Autre que cela, je ne suis pas au courant d'une fonctionnalité de langage qui verrouillera votre fonction de telle manière qu'elle ne soit pas surchargée et puisse toujours être invoquée via un pointeur/référence à la classe enfant.
Bonne chance!
Lorsque vous pouvez utiliser le spécificateur final
pour les méthodes virtuelles (introduites avec C++11), Vous pouvez le faire. Laissez-moi citer mon site doc préféré :
Lorsqu'elle est utilisée dans une déclaration de fonction virtuelle, final spécifie que la fonction ne peut pas être remplacée par des classes dérivées.
Adapté à votre exemple, ce serait comme:
class Base {
public:
virtual bool someGuaranteedResult() final { return true; }
};
class Child : public Base {
public:
bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};
Lors de la compilation:
$ g++ test.cc -std=c++11
test.cc:8:10: error: virtual function ‘virtual bool Child::someGuaranteedResult()’
test.cc:3:18: error: overriding final function ‘virtual bool Base::someGuaranteedResult()’
Lorsque vous travaillez avec un compilateur Microsoft, jetez également un oeil à la sealed
mot.
Sonne comme ce que vous cherchez est l'équivalent du langage Java finale mot clé empêche une méthode d'être remplacée par une sous - .
Comme autres ici ont suggéré, vous ne pouvez vraiment pas vous en empêcher. En outre, il semble que c'est plutôt une question fréquemment posée .
Un avertissement de compilation sur le masquage de la fonction héritée Non virtuelle X.
Modifiez les paramètres de votre compilateur pour en faire une erreur au lieu d'un avertissement.
(a) Je ne pense pas que rendre la fonction privée soit la solution car cela masquera simplement la fonction de classe de base de la classe dérivée.La classe dérivée peut toujours définir une nouvelle fonction avec la même signature. (B) rendre la fonction non virtuelle n'est pas non plus une solution complète car, si la classe dérivée redéfinit la même fonction , on peut toujours appeler la fonction de classe dérivée par liaison au moment de la compilation, c'est-à-dire obj.someFunction() où obj est une instance de la classe dérivée.
Je ne pense pas qu'il y a un moyen de le faire.En outre, j'aimerais connaître la raison de votre décision d'interdire aux classes dérivées de surcharger les fonctions de classe de base.
Je suppose que ce que le compilateur vous avertit est de se cacher !! Est-elle remplacée ?
Le compilateur peut vous donner un avertissement, mais à l'exécution, la méthode de classe parent sera appelée si le pointeur est de type classe parent, quel que soit le type réel de l'objet vers lequel il pointe.
C'est intéressant. Essayez de faire un petit programme de test autonome pour votre compilateur.
Pour clarifier, la plupart d'entre vous ont mal compris sa question. Il ne demande pas de "remplacer" une méthode, il demande s'il existe un moyen d'empêcher "de se cacher" ou non. Et la réponse simple est que " il n'y en a pas!".
Voici son exemple une fois de plus
La classe Parent définit une fonction:
int foo() { return 1; }
Classe enfant, héritant du Parent définit à nouveau la même fonction (Pas de substitution):
int foo() { return 2; }
Vous pouvez le faire sur tous les langages de programmation. Il n'y a rien à empêcher ce code de compiler (sauf un paramètre sur le compilateur). Le meilleur que vous obtiendrez est un avertissement que vous cachez la méthode du parent. Si vous appelez la classe enfant et appelez la méthode foo, vous obtiendrez 2. Vous avez pratiquement cassé le code.
C'est ce qu'il demande.
Je cherchais la même chose et hier est venu à cette question [plutôt ancienne].
Aujourd'hui, j'ai trouvé un mot-clé C++11 soigné : final
. Je pensais que cela pourrait être utile pour les prochains lecteurs.
Si vous adressez la classe enfant en tant que type de son parent, une fonction non virtuelle appellera la version de la classe parent.
Exemple:
Parent* obj = new Child();
Sauf si vous rendez la méthode virtuelle, la classe enfant ne peut pas la remplacer. Si vous voulez empêcher les classes d'enfants de l'appeler, rendez-le privé.
Donc, par défaut, C++ fait ce que vous voulez.
, Essayant d'empêcher quelqu'un d'utiliser le même nom que votre fonction dans une sous-classe n'est pas très différent que d'essayer d'empêcher quelqu'un d'utiliser le même nom de fonction que vous avez déclaré dans une bibliothèque de liens.
Vous pouvez seulement espérer que les utilisateurs qui veulent utiliser votre code, et pas ceux des autres, feront attention à la façon dont ils référencent votre code et qu'ils utilisent le bon type de pointeur ou utilisent une portée complète.
Dans votre exemple, aucune fonction n'est substituée. Il est plutôt caché (c'est une sorte de dégénérés cas de surcharge). L'erreur est dans le code de classe enfant. Comme csmba l'a suggéré, tout ce que vous pouvez faire est de changer les paramètres de votre compilateur (si possible) ; cela devrait être bien tant que vous n'utilisez pas une bibliothèque tierce qui cache ses propres fonctions.
Techniquement, u peut empêcher les fonctions virtuelles d'être remplacées. Mais vous n'aurez jamais été en mesure de changer ou d'ajouter plus. Ce n'est pas de l'aide totale. Mieux vaut utiliser le commentaire devant la fonction comme le suggère faq Lite.
Les méthodes C++ sont privées et non substituables par défaut.
- Vous ne pouvez pas remplacer une méthode privée
- vous ne pouvez pas remplacer une méthode non-
virtual
Parlez-vous peut-être de surcharge?