Question

Je lis Penser en C ++ par Bruce Eckel. Dans le chapitre 15 (Volume 1) sous la rubrique " Comportement des fonctions virtuelles à l'intérieur constructeur ", il va

  

Qu'est-ce qui se passe si vous êtes dans un   constructeur et que vous appelez un virtuel   une fonction? A l'intérieur d'un membre ordinaire   fonction, vous pouvez imaginer ce qui va   arriver - l'appel virtuel est résolu   à l'exécution parce que l'objet ne peut pas   savoir si elle appartient à la classe   la fonction de membre est, ou quelque   classe dérivée de celle-ci. Pour   la cohérence, vous pourriez penser que c'est   ce qui devrait se produire à l'intérieur   constructeurs.

Ici, Bruce essayant d'expliquer que lorsque vous appelez une fonction virtuelle à l'intérieur du constructeur d'un objet, le polymorphisme n'est pas exposé à savoir la fonction classe actuelle ne sera appelé et il ne sera pas une autre version classe dérivée de cette fonction. Ceci est valable et je peux le comprendre, puisque le constructeur d'une classe ne saura pas à l'avance si elle est en cours d'exécution pour elle ou pour la création de someother objet dervied. De plus, si elle le fait, ce sera l'appel de fonctions sur un objet partiellement créé, ce qui est désastreux.

Alors que ma confusion se soudainement à cause de la première phrase où il dit à propos de la fonction membre ordinaire, où il dit l'appel virtuel sera résolu @ l'exécution. Mais attendez, à l'intérieur une fonction membre d'une classe, lorsque vous appelez une autre fonction (que ce soit virtuel ou non virtuel) sa propre version de classe ne sera appelée, non? Par exemple.

class A
{
    virtual void add() { subadd(); }
    virtual subadd() { std::cout << "A::subadd()\n"; }
};

class B : public A
{
    void add() { subadd(); }
    void subadd() { std::cout << "B::subadd()\n"; }
};

Dans le code ci-dessus, A::add() lorsqu'un appel à subadd() est fait, il va toujours A::subadd() d'appel et même pour B aussi bien, non? Alors, qu'est-ce qu'il veut dire par « l'appel virtuel est résolu lors de l'exécution parce que l'objet ne peut pas savoir si elle appartient à la classe la fonction membre est, ou une classe dérivée de celle-ci »?

est-il l'expliquer par rapport à un appel via un pointeur de classe de base ? (Je pense vraiment si) Dans ce cas, il ne doit pas être écrit « A l'intérieur d'une fonction de membre ordinaire »; de ma compréhension à ce jour, tout appel d'une fonction membre à l'intérieur une autre fonction membre de la même classe n'est pas polymorphes, s'il vous plaît me corriger si je suis se tromper.

Était-ce utile?

La solution

Vous avez tort - une autre classe dérivée pourrait remplacer certaines des fonctions virtuelles, ce qui signifie qu'un appel statique serait erroné. Donc, pour prolonger votre exemple:

class C : public B
{
public:
    // Not overriding B::add.
    void subadd() { std::cout << "C::subadd\n"; }
};

A *a = new C;
a->add();

Cette dynamique appelle B::add, qui appelle à son tour dynamiquement C::subadd. Un appel statique B::subadd serait erroné, car le type dynamique est C et C remplace la fonction.

Dans votre exemple, la duplication des A::add comme B::add est inutile -. Toutes les deux appelleront subadd polymorphically quel que soit le type dynamique de l'objet

Autres conseils

  

lorsque vous appelez une autre fonction (que ce soit virtuel ou non virtuel) sa propre version de classe ne sera appelée, non?

Sorry, wrong. Le constructeur est l'exception. Dans le cas contraire, vous avez affaire à un objet entièrement construit pour lequel le polymorphisme complet est en place. Dans votre exemple plus tard (si B hérite de A), ce qu'on appelle le B::subadd() (il suffit de prendre le code pour un essai routier: qui est vraiment la meilleure façon d'apprendre comment fonctionne le langage de programmation).

Le subadd(); d'appel dans vos exemples est vraiment le this->subadd(); d'appel. Dans A::add(), le type de this est A*, mais this peut pointer vers un objet C (en supposant que C dérive d'un trop). Lors de la compilation A::add(), le compilateur ne peut pas savoir quelles fonctions virtuelles sont remplacées dans class C. Le this->subadd(); d'appel dans A::add() peut réellement appeler C::subadd(). Ainsi, le compilateur n'a pas d'autre choix que de mettre dans un appel virtuel, à résoudre lors de l'exécution quand il sait où les points de this-> à.

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