Виртуалы могут иметь значения по умолчанию. Значения по умолчанию в базовом классе не наследуются производными классами.
Какой тип по умолчанию используется, т. Е. Базовый класс или производный класс, определяется статическим типом, используемым для вызова функции. Если вы вызываете объект, указатель или ссылку базового класса, используется значение по умолчанию, обозначенное в базовом классе. И наоборот, если вы вызываете через объект производного класса, указатель или ссылку, используются значения по умолчанию, обозначенные в производном классе. Под стандартной цитатой есть пример, демонстрирующий это.
Некоторые компиляторы могут делать что-то другое, но это то, что говорят стандарты C ++ 03 и C ++ 11:
( РЕДАКТИРОВАТЬ : Стандарт C ++ 11 говорит то же самое)
8.3.6.10:
Виртуальный вызов функции (10.3) использует
аргументы по умолчанию в
объявление виртуальной функции
определенный
статическим типом указателя или ссылки, обозначающей объект.
переопределяющая функция в производном
класс не получает аргументы по умолчанию из функции, которую он
переопределение. [Пример:
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]
Редактировать Вот пример программы, демонстрирующей, какие значения по умолчанию выбраны. Я просто использую struct
здесь, а не class
просто для краткости - class
и struct
практически одинаковы почти во всех отношениях, кроме видимости по умолчанию.
#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;
}
Вывод этой программы (на MSVC10 и GCC 4.4):
Base 42
Der 42
Der 84