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.

25
demandé sur moooeeeep 2008-08-20 10:50:32

14 réponses

Quelques idées:

  1. rendez votre fonction privée.
  2. 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!

12
répondu OJ. 2008-08-20 06:53:40

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.

31
répondu moooeeeep 2017-07-26 18:35:15

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 .

6
répondu Danny Whitt 2017-05-23 12:00:24

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.

2
répondu csmba 2008-08-21 01:20:21

(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.

2
répondu 2008-09-23 12:02:39

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.

1
répondu RuntimeException 2008-09-23 13:13:01

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.

1
répondu LPL 2011-09-26 00:50:04

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.

Http://en.cppreference.com/w/cpp/language/final

1
répondu Abhay Bhave 2016-08-04 06:00:41

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();
0
répondu Ryan Fox 2008-08-20 06:53:36

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.

0
répondu Mark Harrison 2008-08-20 06:57:47

, 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.

0
répondu Mark Cidade 2008-08-21 01:27:11

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.

0
répondu Luc Hermitte 2008-09-23 13:00:30

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.

0
répondu Vlad Sakharuk 2009-12-11 21:51:56

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?

-1
répondu Frank Krueger 2008-08-20 06:54:28