Polymorphisme C ++ et argument par défaut

J’ai ces cours:

class Base { public: virtual void foo(int x = 0) { printf("X = %d", x); } }; class Derived : public Base { public: virtual void foo(int x = 1) { printf("X = %d", x); } }; 

Quand j’ai:

 Base* bar = new Derived(); bar->foo(); 

Ma sortie est “X = 0”, même si foo est appelé depuis Derived, mais quand j’ai:

 Derived* bar = new Derived(); bar->foo(); 

Ma sortie est “X = 1”. Ce comportement est-il correct? (Pour sélectionner la valeur du paramètre par défaut dans le type de déclaration, au lieu de la sélectionner dans le type d’object réel). Est-ce que cela rompt le polymorphism C ++?

Cela peut poser de nombreux problèmes si quelqu’un utilise des fonctions virtuelles sans spécifier le paramètre de fonction réel et utilise le paramètre par défaut de la fonction.

Les arguments par défaut sont conservés même si vous substituez une fonction! Et ce comportement est correct. Permettez-moi de rechercher la référence à partir de la norme C ++.

§8.3.6 / 10 [Arguments par défaut] de la norme C ++ dit:

Un appel de fonction virtuelle (10.3) utilise les arguments par défaut dans la déclaration de la fonction virtuelle déterminée par le type statique du pointeur ou de la référence désignant l’object . Une fonction de substitution dans une classe dérivée n’acquiert pas les arguments par défaut de la fonction qu’elle substitue .

L’exemple de la norme elle-même

 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() } 

En outre, non seulement elle est conservée, mais elle est évaluée chaque fois que la fonction est appelée:

§8.3.6 / 9 dit:

Les arguments par défaut sont évalués chaque fois que la fonction est appelée

Le comportement est correct. Découvrez la réponse à cette question pour une explication:

Les fonctions virtuelles peuvent-elles avoir des parameters par défaut?

Moral: traite les valeurs de paramètre par défaut dans la signature de la fonction et ne les modifie pas lors de la substitution de fonctions virtuelles!

C’est ce que C ++ a conçu, je pense.

Le polymorphism est terminé par la table virtuelle, qui joue en interne avec le pointeur sur les fonctions, mais la valeur par défaut du paramètre n’est pas stockée avec le pointeur de la fonction, il est lié lors de la phase de compilation. , dans votre premier cas, il s’agit de la base, puis il utilise 0 comme valeur par défaut.