3

La sortie de ce code est 15 et je ne sais vraiment pas pourquoi. Je pense qu'il utilise x=5 dans la fonction foo mais je ne sais pas pourquoi. Quelqu'un peut-il m'aider ?Fonction virtuelle avec argument par défaut, sortie bizarre

#include <iostream> 
#include <string> 

using namespace std; 


struct A 
{ 
    virtual int foo(int x = 5) 
    { 
     return x*2; 
    } 
}; 

struct B : public A 
{ 
    int foo(int x = 10) 
    { 
     return x*3; 
    } 
}; 



int main(int argc, char** argv) 
{ 
    A* a = new B; 
    cout << a->foo(); 
    return 0; 
} 
+1

Copie possible de [comportement d'arguments par défaut de la fonction virtuelle] (http://stackoverflow.com/questions/6464404/virtual-function-default-arguments-behaviour) – cpplearner

Répondre

6

Je pense qu'il utilise x=5 dans la fonction foo mais je ne sais pas pourquoi.

Oui, l'argument par défaut de déclaration de la classe de base A (à savoir 5) est utilisé ici, parce que vous appelez foo() sur un objet de type statique A*. Les default arguments sont déterminés en fonction du type statique, autre que le type dynamique.

La norme a une explication claire à ce sujet, $8.3.6/10 Default arguments [dcl.fct.default]:

(Souligné par l'auteur)

Un appel de fonction virtuelle ([class.virtual]) utilise les arguments par défaut dans la déclaration de la fonction virtuelle déterminée par le statique type du pointeur ou référence désignant l'objet. Une fonction dominante dans une classe dérivée n'acquiert pas les arguments par défaut de la fonction qu'elle remplace. [Exemple:

struct A { 
    virtual void f(int a = 7); 
}; 
struct B : public A { 
    void f(int a); 
}; 
void m() { 
    B* pb = new B; 
    A* pa = pb; 
    pa->f();   // OK, calls pa->B::f(7) 
    pb->f();   // error: wrong number of arguments for B::f() 
} 

- exemple final]

3

Il y a deux parties à cette invocation:

  • Décider quelle valeur pour passer à x - c'est le paramètre par défaut A::foo, soit 5, parce que c'est statique type de a, soit le type connu à compiler le temps. Si vous y réfléchissez, c'est le seul choix du compilateur, car il ne doit pas faire d'hypothèses sur le type affecté à a.
  • Décider quelle classe reçoit l'appel - c'est B::foo, parce que le type dynamique de l'objet pointé par a est struct B.

D'où vous obtenez 3 * 5 comme votre sortie.