Quelles sont les différences entre le remplacement des fonctions virtuelles et le masquage de non-fonctions virtuelles?
Donné le fragment de code suivant, quelles sont les différences dans les appels de fonction? Qu'est-ce que la fonction de masquage? Qu'est-ce que la fonction primordiale? Comment ils se rapportent à la fonction de surcharges? Quelle est la différence entre les deux? Je ne pouvais pas trouver une bonne description de ces documents en un seul endroit, donc je pose la question ici afin que je puisse consolider les informations.
class Parent {
public:
void doA() { cout << "doA in Parent" << endl; }
virtual void doB() { cout << "doB in Parent" << endl; }
};
class Child : public Parent {
public:
void doA() { cout << "doA in Child" << endl; }
void doB() { cout << "doB in Child" << endl; }
};
Parent* p1 = new Parent();
Parent* p2 = new Child();
Child* cp = new Child();
void testStuff() {
p1->doA();
p2->doA();
cp->doA();
p1->doB();
p2->doB();
cp->doB();
}
Comment pouvez-vous pas trouver une bonne description? Ce qui est couvert dans toute base de C++ manuel. (Et avec un accès public pour les fonctions de membre.)
Ce sent comme un devoir à la maison ou quelque chose comme ça. Je ne sais pas pourquoi que vous souhaitez poser une question qui est si largement couverts.
Je ne peux pas trouver une explication en ligne (qui est l'endroit où j'ai l'habitude de regarder, et d'autres sans doute aussi) que compare ces. Ils ont des explications de l'un ou de l'autre, mais pas les deux, et je voulais mettre quelque chose en ligne qui serait facile de référence. Merci pour les captures sur les spécificateurs d'accès.
Non, c'est juste quelque chose que j'ai trouvé. Les explications que j'ai trouvé expliquer l'un ou l'autre, mais ne pas donner une comparaison, et c'est ce que je suis en train de.
FWIW, je m'apprêtais à poster cette même question, et non, ce n'est pas pour un devoir à la maison. Je suis longtemps hors de l'université. Merci de poser cette Jed, bien que malheureusement je ne comprends toujours pas ce que le mot clé virtual est pour, sauf si vous essayez de faire une classe de base abstraite avec des fonctions virtuelles pures. En dehors de cela, je ne vois pas ce "virtuel" d'un point de vue pratique, car je peux juste masquer la fonction.
Ce sent comme un devoir à la maison ou quelque chose comme ça. Je ne sais pas pourquoi que vous souhaitez poser une question qui est si largement couverts.
Je ne peux pas trouver une explication en ligne (qui est l'endroit où j'ai l'habitude de regarder, et d'autres sans doute aussi) que compare ces. Ils ont des explications de l'un ou de l'autre, mais pas les deux, et je voulais mettre quelque chose en ligne qui serait facile de référence. Merci pour les captures sur les spécificateurs d'accès.
Non, c'est juste quelque chose que j'ai trouvé. Les explications que j'ai trouvé expliquer l'un ou l'autre, mais ne pas donner une comparaison, et c'est ce que je suis en train de.
FWIW, je m'apprêtais à poster cette même question, et non, ce n'est pas pour un devoir à la maison. Je suis longtemps hors de l'université. Merci de poser cette Jed, bien que malheureusement je ne comprends toujours pas ce que le mot clé virtual est pour, sauf si vous essayez de faire une classe de base abstraite avec des fonctions virtuelles pures. En dehors de cela, je ne vois pas ce "virtuel" d'un point de vue pratique, car je peux juste masquer la fonction.
OriginalL'auteur Jed Schaaf | 2013-11-01
Vous devez vous connecter pour publier un commentaire.
Qu'est-ce que la fonction de masquage?
... est une forme du nom de la clandestinité. Un exemple simple:
Cela s'applique également à la recherche d'un nom dans une classe de base:
Qu'est-ce que la fonction primordiale?
Cela est lié à la notion de fonctions virtuelles. [classe.virtuel]/2
La finale overrider devient pertinente lors de l'appel d'une fonction virtuelle: [classe.virtuel]/2
I. e. si vous avez un objet de type
S
, la finale overrider est la première overrider vous voir lors de la traversée de la hiérarchie de classe deS
retour à de ses classes de base. Le point important est que la de type dynamique de la fonction-appel expression est utilisée afin de déterminer la finale overrider:Quelle est la différence entre le remplacement et la cacher?
Essentiellement, les fonctions dans la classe de base sont toujours cachés par des fonctions de même nom dans une classe dérivée, peu importe si la fonction dans la classe dérivée remplace une classe de base virtuelle ou non la fonction:
Pour trouver un nom de fonction, le type statique d'une expression est utilisée:
Comment ils se rapportent à la fonction de surcharges?
Que la fonction "cacher" est une forme du nom de la clandestinité, tous les surcharges sont touchés si le nom d'une fonction est caché:
Pour fonction dominante, seule la fonction dans la classe de base avec les mêmes arguments seront redéfinies; vous pouvez bien sûr la surcharge d'une fonction virtuelle:
Je n'ai pas inclure le type de retour dans les commentaires but: Seul le nom est pertinent pour le nom de masquage, et seulement le nom et les paramètres sont pertinents pour annuler. Le type de retour ne peut faire une substitution illégale, si elle n'est pas identique ou covariants pour le type de retour de la remplacée fonction.
Sur la même ligne, même si, vous avez que vf2(int), les remplacements et les peaux vf(int). Une modification doit avoir au moins 6 caractères, donc j'ai ajouté quelque chose que je pensais peut-être hors de propos. Désolé de ne pas être clair. :/
Oh, merci! C'est effectivement une faute de frappe. Ouais.. le système de montage de SORTE décourage (ou doit décourager) ce genre de petites modifications, comme chaque modification doit être examiné par plusieurs personnes. Voir cette discussion sur Meta Stack Overflow.
Il est également intéressant de noter que, si une non-méthode virtuelle
Base::foo()
appelle une méthode virtuelleBase::vf()
dans la classe de base, puis de l'appel d'foo()
à partir d'une classe dérivée de déclencher la méthode de remplacementDerived::vf()
, et non pas l'originalBase::vf()
.OriginalL'auteur dyp
La différence entre l'appel d'une virtuel fonction de membre et l'appel d'une non virtuelle fonction de membre, c'est que, par définition, dans le premier cas, la fonction cible est choisi en conformité avec le dynamique type de l'objet de l'expression utilisée dans l'appel, tandis que dans le second cas, le statique type est utilisé.
C'est tout là est à lui. Votre exemple illustre clairement cette différence par
p2->doA()
etp2->doB()
appels. Type statique de*p2
expression estParent
, tandis que le type dynamique de la même expression estChild
. C'est pourquoip2->doA()
appelsParent::doA
etp2->doB()
appelsChild::doB
.Dans les contextes dans lesquels cette différence, le nom de la clandestinité ne vient pas dans l'image.
Le premier paragraphe résume toute les réponses possibles et de toutes les de 100 exemples. Merci!
OriginalL'auteur AnT
Beaucoup plus de facilité exemple qui diffère b/w tous.
OriginalL'auteur AbhimanyuAryan
L'exemple de code que vous avez écrit dans la question donne la réponse lorsque vous l'exécutez.
L'appel d'une fonction non virtuelle utilisera la fonction de la même catégorie que le type de pointeur, indépendamment de savoir si l'objet a été effectivement créé comme un autre type dérivé. Alors que l'appel d'une fonction virtuelle utilisera la fonction à partir de l'original alloué type d'objet, quel que soit le type de pointeur que vous utilisez.
De sorte que votre programme de sortie dans ce cas sera:
OriginalL'auteur karadoc
Nous allons commencer par le plus facile.
p1
est unParent
pointeur, donc il sera toujours appelerParent
's des fonctions de membre du.cp
est un pointeur versChild
, de sorte qu'il sera toujours appelerChild
's des fonctions de membre du.Maintenant le plus difficile.
p2
est unParent
pointeur, mais il pointe vers un objet de typeChild
, ce qui fera appel àChild
's fonctions chaque fois que le correspondantParent
fonction est virtuelle ou la fonction n'existe que dans lesChild
et pas dansParent
. En d'autres termes,Child
cacheParent::doA()
avec ses propresdoA()
, mais il remplaceParent::doB()
. La fonction de masquage est parfois considéré comme une forme de la surcharge de fonction, parce que d'une fonction avec le même nom est donné à une mise en œuvre différente. Parce que le masquage de la fonction est dans une classe différente de celle de la fonction cachée, il a une signature différente, ce qui rend clair pour l'utiliser.La sortie pour
testStuff()
seraDans tous les cas,
Parent::doA()
etParent::doB()
peut être appelée à l'intérieurChild
à l'aide de la résolution de nom, quelle que soit la fonction "virtual-ness". La fonctiondémontre lorsqu'il est appelé par
cp->doX()
par la sortieEn outre,
cp->Parent::doA()
appelleraParent
'version dedoA()
.p2
ne peut pas se référer àdoX()
parce que c'est unParent*
, etParent
ne sais pas à propos de quoi que ce soit dansChild
. Cependant,p2
peut être castée pour unChild*
, depuis qu'il a été initialisé comme un seul, et alors il peut être utilisé pour appelerdoX()
.Probablement parce que c'est le même gars qui a posé la question. Donc on dirait qu'il vient de poser la question pour obtenir quelques points de réputation plutôt que de réellement apprendre quelque chose.
Pourquoi supposez-vous que je n'ai pas appris cela? Je n'avais pas regardé ces sujets pendant un certain temps, j'ai donc décidé de le regarder. Quand je ne pouvais pas trouver rapidement exactement ce que je cherchais, j'ai décidé de l'ajouter ici comme une référence pour les autres qui pourraient avoir des questions similaires. Ne vous n'aimez pas que j'ai répondu à ma propre question? La question de la soumission a la possibilité d'ajouter une réponse immédiatement, de "partager vos connaissances, Q&Un style."
upvoted pour l'initiative
OriginalL'auteur Jed Schaaf