Os virtuais podem ter padrões. Os padrões na classe base não são herdados pelas classes derivadas.
Qual padrão é usado - ou seja, a classe base 'ou uma classe derivada' - é determinada pelo tipo estático usado para fazer a chamada para a função. Se você chamar através de um objeto, ponteiro ou referência da classe base, o padrão indicado na classe base será usado. Por outro lado, se você chamar através de um objeto de classe derivada, ponteiro ou referência serão usados os padrões indicados na classe derivada. Há um exemplo abaixo da cotação padrão que demonstra isso.
Alguns compiladores podem fazer algo diferente, mas é o que dizem os padrões C ++ 03 e C ++ 11:
8.3.6.10:
Uma chamada de função virtual (10.3) usa os argumentos padrão na declaração da função virtual determinada pelo tipo estático do ponteiro ou referência que indica o objeto. Uma função de substituição em uma classe derivada não adquire argumentos padrão da função que substitui. Exemplo:
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()
}
Aqui está um exemplo de programa para demonstrar quais padrões são selecionados. Estou usando struct
s aqui em vez de class
es simplesmente por questões de brevidade - class
e struct
são exatamente iguais em quase todos os aspectos, exceto na visibilidade padrão.
#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;
}
A saída deste programa (no MSVC10 e GCC 4.4) é:
Base 42
Der 42
Der 84