Appel de méthode de classe de base à partir d'objet de classe dérivée
Comment puis-je appeler une méthode de classe de base qui est remplacée par la classe dérivée, à partir d'un objet de classe dérivée?
class Base{
public:
void foo(){cout<<"base";}
};
class Derived:public Base{
public:
void foo(){cout<<"derived";}
}
int main(){
Derived bar;
//call Base::foo() from bar here?
return 0;
}
- connexes: stackoverflow.com/q/2437586/951890
- Ce n'est pas remplacée si elle n'est pas virtuelle,
Derived::foo
plutôt se cacheBase::foo
. - Merci c'est très bon à savoir 🙂
- Cela ressemble à un problème de conception. Si
Derived
a sa propre version defoo
, les chances sont que c'est pas conçu pour se comporter correctement, si quelqu'un en dehors de la classe appelle la version de base à la place. - Double Possible de Comment appeler un parent de la classe de fonction à partir de la classe dérivée de la fonction?
Vous devez vous connecter pour publier un commentaire.
Vous pouvez toujours(*) se référer à une classe de base de la fonction en utilisant un qualifié-id:
[Également corrigé quelques fautes de frappe de l'OP.]
(*) L'accès restrictions continuent de s'appliquer, et les classes de base peut être ambigu.
Si
Base::foo
n'est pasvirtual
, puisDerived::foo
ne pas remplacerBase::foo
. Plutôt,Derived::foo
cacheBase::foo
. La différence peut être vu dans l'exemple suivant:(
Derived::bar
est implicitement virtuel, même si vous n'utilisez pas levirtual
mot-clé, tant que c'est la signature est compatible àBase::bar
.)Un qualifié-id est soit de la forme
X :: Y
ou tout simplement:: Y
. La partie avant de la::
spécifie l'endroit où nous voulons rechercher l'identifiantY
. Dans la première forme, nous attendons jusqu'à laX
, puis nous regardonsY
de l'intérieurX
s'contexte. Dans la deuxième forme, nous attendons jusqu'à laY
dans l'espace de noms global.Un unqualified-id ne contient pas de
::
, et n'a donc pas (lui-même) spécifier un contexte où rechercher le nom.Dans une expression
b->foo
, à la foisb
etfoo
sont unqualified-id.b
est recherché dans le contexte actuel (dans l'exemple ci-dessus est lemain
fonction). Nous constatons que la variable localeBase* b
. Parce queb->foo
a la forme d'un membre de la classe d'accès, nous attendons jusqu'à lafoo
à partir du contexte, du type deb
(ou plutôt*b
). Si nous attendons jusqu'à lafoo
à partir du contexte deBase
. Nous allons trouver la fonction de membre devoid foo()
déclarée à l'intérieur d'Base
, que j'appelleraiBase::foo
.Pour
foo
, nous y sommes maintenant, et appelBase::foo
.Pour
b->bar
, nous trouvons d'abordBase::bar
, mais il est déclarévirtual
. Parce que c'estvirtual
, nous procédons à une virtuel expédition. Ce qui fera appel à la fonction finale overrider dans la hiérarchie de classe du type de l'objetb
points. Parce queb
pointe vers un objet de typeDerived
, la finale overrider estDerived::bar
.Lorsque l'on cherche le nom
foo
deDerived
's contexte, nous allons trouverDerived::foo
. C'est pourquoiDerived::foo
est dit cacherBase::foo
. Des Expressions telles qued.foo()
ou, à l'intérieur d'une fonction membre deDerived
, en utilisant simplementfoo()
outhis->foo()
, va chercher du contexte deDerived
.Lors de l'utilisation d'un qualifié-id, nous avons explicitement état du contexte où pour rechercher un nom. L'expression
Base::foo
états que nous voulons rechercher le nomfoo
à partir du contexte deBase
(on peut trouver des fonctions quiBase
hérité, par exemple). En outre, il désactive virtuel de l'expédition.Par conséquent,
d.Base::foo()
trouverezBase::foo
et de l'appeler;d.Base::bar()
trouverezBase::bar
et de l'appeler.Fait amusant: des fonctions virtuelles Pures peut avoir une mise en œuvre. Ils ne peuvent pas être appelé via le virtuel expédition, parce qu'ils besoin d'être redéfinie. Cependant, vous pouvez toujours faire appel à leur mise en œuvre (si ils en ont un) à l'aide d'un qualifié-id.
Noter que accès spécificateurs de à la fois de membres de la classe et les classes de base ont une influence sur si oui ou non vous pouvez utiliser un qualifié-id pour appel d'une classe de base de la fonction sur un objet d'un type dérivé.
Par exemple:
L'accessibilité est orthogonal à la recherche d'un nom. Si le nom de la clandestinité n'a pas d'influence sur elle (vous pouvez les laisser dehors
public_fun
etprivate_fun
dans les classes dérivées et avoir le même comportement et les erreurs pour les qualifiés-id appels).L'erreur dans
p.Base::private_fun()
est différente de l'erreur dansr.Base::public_fun()
par la voie: La première, déjà omet de mentionner le nomBase::private_fun
(parce que c'est un privé nom). Le second ne parvient pas à convertirr
dePrivate_derived&
àBase&
pour lathis
-pointeur (pour l'essentiel). C'est pourquoi la seconde travaille de l'intérieurPrivate_derived
ou un ami dePrivate_derived
.Base::foo
. À l'aide d'une personne qualifiée, id pour appeler une classe de base fonctionne indépendamment de ce qui se passe à cette fonction dans la classe dérivée - il peut être caché, elle peut être remplacée, il peut être fait privé (à l'aide d'un aide-déclaration), vous avez directement accès à la base de la classe de fonction lors de l'utilisation d'un personnel qualifié-id.Premier de tous les Dérivés doivent hériter de Base.
Que dit
D'abord, vous pouvez tout simplement pas avoir foo dans la Dérivée
Deuxième vous pouvez faire Dérivés::foo appel de Base::foo.
Tiers, vous pouvez utiliser un id de Base::foo
Envisager de faire
foo()
virtuel en premier lieu.Cependant, ce fait le travail:
bar.Base::foo()
bar.Base::foo();
pour accéder à la méthode de classe de base droit?void Base1::begin(){\\initialization}
,class Derived:public Base1, public Base2{...}; void Derived::begin(){\\initialization}
, de sorte que l'architecture est malheureusement hors de ma portée 🙁 Et juste essayer de faire une hackish test ici 🙂Un important [autres] note: vous aurez encore des erreurs de compilation si Nom de Cacher se produit.
Dans ce cas, soit utiliser l'aide de mots clés ou d'utiliser le qualifer. En outre, voir cette réponse ainsi.