2010-06-29 18 views
4

Je suis l'apprentissage de polymorphisme, et je suis confus par cette situation: Disons que j'ai les classes C++ suivantes:Si une fonction C++ remplacée appelle la fonction parente, qui appelle une autre fonction virtuelle, comment s'appelle-t-elle?

class A{ 
    ... 
    virtual void Foo(){ 
     Boo(); 
    } 
    virtual void Boo(){...} 
} 

class B : public A{ 
    ... 
    void Foo(){ 
     A::Foo(); 
    } 
    void Boo(){...} 
} 

Je crée une instance de B et appeler sa fonction Foo(). Lorsque cette fonction appelle A :: Foo(), la méthode Boo() utilisée sera-t-elle celle de la classe A ou B? Merci!

+2

Eh bien essayer et voir ce qui se passe! – Goz

+14

Je n'aime pas ces commentaires "essayez-le vous-même". Ce que vous découvrez en train de l'essayer vous-même est ce que votre compilateur fait sous les circonstances artificielles de votre test. Ce n'est peut-être pas ce que tu voulais savoir. Bien que je puisse voir que, dans ce cas, il est difficile d'imaginer un compilateur qui se trompe, que faire si ODdol, pas sûr de savoir comment 'virtual' fonctionne, configurer le test afin que la fonction est appelée à partir du constructeur de la classe? Une telle erreur pourrait renvoyer un étudiant deux semaines en arrière. __À la fin, ce site est pour obtenir des réponses. Si les questions vous ennuient, pourquoi les lisez-vous? – sbi

+0

@sbi: Non, mais c'est un bon point de départ. Comme dans: J'ai cette question, et voici ce que je vois. Est-ce normal? – Bill

Répondre

9

À moins que vous qualifiez un appel de fonction à la classe, tous les appels de méthode seront traités égaux, est l'envoi dynamique si l'expédition virtuelle, statique sinon virtuel. Lorsque vous vous qualifiez pleinement avec le nom de classe, la méthode que vous appelez désactive le mécanisme de répartition dynamique et introduit un appel de méthode directe.

class A{ 
    virtual void Foo(){ 
     Boo();   // will call the final overrider 
     A::Boo();  // will call A::Boo, regardless of the dynamic type 
    } 
    virtual void Boo(); 
}; 
class B : public A{ 
    void Foo(){ 
     //Foo();   // Would call the final overrider 
         // (in this case B: infinite recursion) 
     A::Foo();  // Will call A::Foo, even if the object is B 
    } 
    void Boo(); 
}; 

Le pointeur this implicite n'est pas une partie importante de la discussion ici, comme exactement la même chose se produit lorsque l'appel est fait avec un objet explicite:

B b; 
b.Foo(); // will call B::Foo -- note 1 
b.A::Foo(); // will call A::Foo 

Note 1: dans cet exemple, le compilateur peut élider le mécanisme de répartition dynamique car il connaît le type concret de l'instance (il voit la définition et ce n'est pas une référence/pointeur) mais vous pouvez imaginer la même chose si b était une référence, ou de manière équivalente si elle était un pointeur avec -> au lieu de .

2

Puisque Boo() est virtuel, la classe dérivée 'override est appelée.

Boo(); est à une courte main pour this->Boo();, où vous pouvez voir qu'une fonction virtuelle est appelée par un pointeur. (this est de type A* const au sein de Foo().) Et les fonctions virtuelles appelées via une référence ou un pointeur appellent toujours le remplacement dans la classe la plus dérivée (sauf lorsqu'elles sont appelées depuis un constructeur ou un destructeur).

1

Inside A,

virtual void Foo(){ 
     Boo(); 
    } 

est traduite à this->Boo(), puisque Boo est déclarée virtuelle dans A, la méthode de la classe dérivée Boo est appelée. Essayez de ne pas déclarer Boo comme virtuel dans A juste pour l'expérimentation - vous verriez que A-> Boo() est appelé.

Arpan