Existe-t-il un moyen d'empêcher qu'une méthode soit remplacée dans les sous-classes ?

StackOverflow https://stackoverflow.com/questions/17483

  •  09-06-2019
  •  | 
  •  

Question

Quelqu'un connaît-il une fonctionnalité ou une technique de langage en C++ pour empêcher une classe enfant de remplacer 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 au moment de la compilation concernant le masquage de la fonction X héritée non virtuelle.

Était-ce utile?

La solution

Quelques idées :

  1. Rendez votre fonction privée.
  2. Ne rendez pas votre fonction virtuelle.Cela n'empêche cependant pas la fonction d'être masquée par une autre définition.

En dehors de cela, je ne connais pas de fonctionnalité de langage qui verrouille votre fonction de manière à l'empêcher d'être surchargée et à pouvoir toujours être invoquée via un pointeur/référence à la classe enfant.

Bonne chance!

Autres conseils

Quand pouvez-vous utiliser le final spécificateur pour les méthodes virtuelles (introduit avec C++11), vous pouvez le faire.Permettez-moi de citer mon site de documentation préféré:

Lorsqu'il est utilisé 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, cela ressemblerait à :

class Base {
public:
    virtual bool someGuaranteedResult() final { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

Une fois compilé :

$ 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 œil au sealed mot-clé.

On dirait que ce que vous recherchez est l'équivalent du langage Java final mot-clé qui empêche qu'une méthode soit remplacée par une sous-classe.

Comme autres ici j'ai suggéré, vous ne pouvez vraiment pas empêcher cela.De plus, il semble que ce soit plutôt une question fréquemment posée.

(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 du Classe dérivée.

Je ne pense pas qu'il existe un moyen de le faire. De plus, j'aimerais connaître la raison de votre décision d'interdire aux classes dérivées de remplacer les fonctions de classe de base.

Pour précision, 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 ou non de "se cacher".Et la réponse simple est : « il n’y en a pas ! ».

Voici encore une fois son exemple

La classe parent définit une fonction :

int foo() { return 1; }

La classe enfant, héritant du Parent, définit ENCORE la même fonction (sans remplacement) :

int foo() { return 2; }

Vous pouvez le faire sur tous les langages de programmation.Rien n’empêche la compilation de ce code (sauf un réglage sur le compilateur).Le mieux que vous obtiendrez est un avertissement indiquant que vous cachez la méthode du parent.Si vous appelez la classe enfant et invoquez la méthode foo, vous obtiendrez 2.Vous avez pratiquement déchiffré le code.

C'est ce qu'il demande.

un avertissement au moment de la compilation concernant le masquage de la fonction X héritée non virtuelle.

modifiez les paramètres de votre compilateur pour en faire une erreur au lieu d'un avertissement.

Je suppose que ce dont le compilateur vous avertit se cache !!Est-il réellement remplacé ?

Le compilateur peut vous donner un avertissement, mais au moment de l'exécution, la méthode de la 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 créer un petit programme de test autonome pour votre compilateur.

Je cherchais la même chose et hier je suis arrivé à cette question [plutôt ancienne].

Aujourd'hui, j'ai trouvé un mot-clé C++11 intéressant : final .J'ai pensé que cela pourrait être utile aux prochains lecteurs.

http://en.cppreference.com/w/cpp/langue/final

Si vous abordez la classe enfant comme un type de son parent, alors une fonction non virtuelle appellera la version de la classe parent.

c'est à dire:

Parent* obj = new Child();

Sauf si vous rendez la méthode virtuelle, la classe enfant ne peut pas la remplacer.Si vous souhaitez empêcher les classes enfants de l'appeler, rendez-le privé.

Donc, par défaut, C++ fait ce que vous voulez.

Essayer 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 d'essayer d'empêcher quelqu'un d'utiliser le même nom de fonction global que celui que vous avez déclaré dans une bibliothèque liée.

Vous pouvez seulement espérer que les utilisateurs qui ont l'intention d'utiliser votre code, et pas celui des autres, feront attention à la façon dont ils référencent votre code et qu'ils utiliseront le bon type de pointeur ou utiliseront une portée pleinement qualifiée.

Dans votre exemple, aucune fonction n'est remplacée.Il est au contraire caché (c'est une sorte de cas de surcharge dégénéré).L'erreur réside dans le code de la classe enfant.Comme csmba l'a suggéré, tout ce que vous pouvez faire est de modifier les paramètres de votre compilateur (si possible) ;cela devrait aller tant que vous n'utilisez pas de bibliothèque tierce qui cache ses propres fonctions.

Techniquement, vous pouvez empêcher le remplacement des fonctions virtuelles.Mais vous ne pourrez jamais modifier ou ajouter davantage.Ce n’est pas une aide complète.Mieux vaut utiliser le commentaire devant la fonction comme le suggère la FAQ Lite.

Les méthodes C++ sont privées et ne peuvent pas être remplacées par défaut.

  • Vous ne pouvez pas remplacer une méthode privée
  • Vous ne pouvez pas remplacer un non-virtual méthode

Peut-être parlez-vous de surcharge ?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top