Virtuals peuvent avoir des valeurs par défaut. Les valeurs par défaut dans la classe de base ne sont pas héritées par les classes dérivées.
Qui par défaut est utilisée, c'est à dire, la classe de base ou d'une classe dérivée' -- est déterminé par le type statique utilisé pour faire l'appel à la fonction. Si vous appelez par l'intermédiaire d'un objet de classe de base, pointeur ou de référence, la valeur par défaut indiqué dans la classe de base est utilisé. A l'inverse, si vous l'appelez par l'intermédiaire d'un objet de classe dérivée, pointeur ou de référence, les valeurs par défaut indiqué dans la classe dérivée sont utilisés. Il y a un exemple en dessous de la Norme citation qui illustre cela.
Certains compilateurs peuvent faire quelque chose de différent, mais c'est ce que le C++03 et C++11 Normes de dire:
(EDIT: Le C++11 Standard dit exactement la même chose)
8.3.6.10:
Un appel de fonction virtuelle (10.3) utilise
les arguments par défaut dans le
déclaration de la fonction virtuelle
déterminé
par le type statique de l'pointeur ou une référence désignant l'objet. Un
fonction dominante dans une dérivée
la classe n'a pas d'acquérir des arguments par défaut de la fonction qu'il
les remplacements. [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()
}
-end example]
Edit Voici un exemple de programme pour démontrer que les valeurs par défaut sont ramassés. Je suis à l'aide d' struct
s ici plutôt que d' class
es tout simplement pour des raisons de concision -- class
et struct
sont exactement les mêmes dans presque tous les sens, sauf défaut de visibilité.
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using std::stringstream;
using std::string;
using std::cout;
using std::endl;
struct Base { virtual string Speak(int n = 42); };
struct Der : public Base { string Speak(int n = 84); };
string Base::Speak(int n)
{
stringstream ss;
ss << "Base " << n;
return ss.str();
}
string Der::Speak(int n)
{
stringstream ss;
ss << "Der " << n;
return ss.str();
}
int main()
{
Base b1;
Der d1;
Base *pb1 = &b1, *pb2 = &d1;
Der *pd1 = &d1;
cout << pb1->Speak() << "\n" // Base 42
<< pb2->Speak() << "\n" // Der 42
<< pd1->Speak() << "\n" // Der 84
<< endl;
}
La sortie de ce programme (sur MSVC10 et GCC 4.4) est:
Base 42
Der 42
Der 84