9
votes

Comment accéder à la méthode protégée dans la classe de base de la classe dérivée?

Voici un échantillon de code qui m'agace: xxx

Comment accéder à la fonction prévisionnelle protégée?

Merci pour votre aide. : o)


5 commentaires

Je ne pense pas que votre mise en œuvre ait bien raison. Pourquoi avez-vous une instance de base en tant que variable membre? Ceci-> B-> FOO () tenterait d'appeler une méthode virtuelle pure.


Ce programme ne devrait pas compiler. Vous ne pouvez pas instancier une classe abstraite ... Sauf si B indique une instance d'une autre classe dérivée de base .


J'ai omis de précision: l'attribut dérivé :: B est destiné à stocker une instance de classes dérivées de la base


Voir aussi Stackoverflow.com/questions / 3247671 / ... (c'est à propos des membres au lieu de méthodes, mais ils ne sont pas très différents)


C ++ les appelle les fonctions membres, non pas des méthodes (bien que certaines personnes utilisent ce dernier, mais dans mon expérience qui conduit à des arguments linguistiques), et les concepts sont les mêmes pour les fonctions membres et les variables des membres, donc: duplicata de


6 Réponses :


6
votes

Normalement, vous le feriez en utilisant Base :: FOO () , qui fait référence à la classe de base de l'instance actuelle.

Toutefois, si votre code doit le faire comme si vous essayez de l'essayer et que vous n'êtes pas autorisé, vous aurez alors besoin de faire du public () public ou de faire dérivé un ami de base.


0 commentaires

0
votes

Vous appelez explicitement les fonctions de base avec l'opérateur de la portée (base :: FOO ()). Mais dans ce cas, la classe de base ne définit pas FOO (c'est pur virtuel), il n'y a donc aucune fonction d'exécution lorsque vous dites this-> b-> foo (); car b est un pointeur à base et non dérivé.


2 commentaires

Mais le code de l'OP ne fait pas référence à la classe de base de l'instance actuelle. Il accède à un autre instance, qui est probablement une classe dérivée qui implémente la fonction pure-virtuelle. (Sinon, l'instance n'a pas pu être créée.)


@Jonathan bois Je comprends ce que vous dites, mais juste du code, il est affiché, il semble qu'il tente d'instancier une classe de base abstraite (base) et d'appeler une fonction virtuelle pure (base :: foo ()), qui est un non-non (comme GWW et 341008 également mentionné ci-dessus).




11
votes

Les membres protégés dans une classe de base ne sont accessibles que par l'objet actuel.
Ainsi, vous êtes autorisé à appeler this-> foo () , mais vous n'êtes pas autorisé à appeler this-> b-> foo () . Ceci est indépendant de savoir si dérivé fournit une implémentation pour foo ou non.

La raison de cette restriction est qu'il serait très facile de contourner l'accès protégé. Vous venez de créer une classe comme dérivé et que vous avez tout à coup, vous avez également accès à des parties d'autres classes (comme autreté injustifié ) censé être inaccessible aux étrangers.


3 commentaires

Merci, je comprends maintenant clairement les raisons de la restriction ... ce serait un trou de sécurité ... grand!


S'il vous plaît ne pensez pas à cela comme un trou de sécurité. Les modificateurs d'accès ne fournissent aucune sécurité, vous pouvez simplement lire l'emplacement de la mémoire si vous souhaitiez les données.


Droite, cela ne concerne pas "la sécurité", mais plutôt de dire aux utilisateurs quelles parties de la classe qu'ils peuvent utiliser et s'appuyer sur (c'est-à-dire que les parties ne sont pas des détails de mise en œuvre qui pourraient disparaître / changer à tout moment). Bien sûr, ils ne devraient pas lire ce genre de choses et devront utiliser des acrobatics avec des trucs comme offset de pour le faire, mais il ne s'agit certainement pas de la sécurité dans le sens de l'accès physique à l'accès aux données - uniquement de documentation prévue. Utilisation, sémantique et stabilité de l'API.



1
votes

C'est un peu fragile, mais avec les classes que vous avez définies ici, cela ne fonctionnera pas?

virtual void foo2() {
  reinterpret_cast<Derived *>(this->b)->foo(); 
}


0 commentaires

3
votes

Une solution serait de déclarer une fonction protégée statique dans base qui redirige l'appel à la fonction privée / protégée ( foo dans l'exemple).

permet dire: xxx

de cette façon, nous ne casserons pas l'encapsulation car le concepteur de base peut faire un choix explicite pour permettre à toutes les classes dérivées d'appeler foo les uns sur les autres, tout en évitant de mettre foo dans l'interface publique ou de tourner explicitement toutes les sous-classes possibles de base en amis.

En outre, cette méthode fonctionne, que foo soit virtuel ou non, ou si elle est privée ou protégée.

ici est un lien vers une version exécutée du code ci-dessus et ici < / a> Une autre version de la même idée avec un peu plus de logique commerciale.


0 commentaires