Los virtuales pueden tener valores predeterminados. Los valores predeterminados en la clase base no son heredados por las clases derivadas.
El valor predeterminado que se usa, es decir, la clase base 'o una clase derivada', está determinado por el tipo estático utilizado para realizar la llamada a la función. Si llama a través de un objeto de clase base, puntero o referencia, se utiliza el valor predeterminado indicado en la clase base. Por el contrario, si llama a través de un objeto de clase derivada, puntero o referencia, se utilizan los valores predeterminados indicados en la clase derivada. Hay un ejemplo debajo de la cita estándar que lo demuestra.
Algunos compiladores pueden hacer algo diferente, pero esto es lo que dicen los estándares C ++ 03 y C ++ 11:
8.3.6.10:
Una llamada a función virtual (10.3) utiliza los argumentos predeterminados en la declaración de la función virtual determinada por el tipo estático del puntero o referencia que denota el objeto. Una función de anulación en una clase derivada no adquiere argumentos predeterminados de la función que anula. Ejemplo:
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()
}
Aquí hay un programa de muestra para demostrar qué valores predeterminados se seleccionan. Estoy usando struct
s aquí en lugar de class
es simplemente por brevedad, class
y struct
son exactamente iguales en casi todos los aspectos, excepto en la visibilidad predeterminada.
#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 salida de este programa (en MSVC10 y GCC 4.4) es:
Base 42
Der 42
Der 84