У віртуалах можуть бути за замовчуванням. За замовчуванням у базовому класі не успадковуються похідні класи.
Який за замовчуванням використовується - тобто базовий клас 'або похідний клас', визначається статичним типом, який використовується для здійснення виклику функції. Якщо ви телефонуєте через об'єкт, вказівник або посилання базового класу, використовується базовий клас, позначений у базовому класі. І навпаки, якщо ви зателефонуєте через похідний об'єкт класу, вказівник або посилання використовуються за замовчуванням, позначені у похідному класі. Нижче є приклад "Стандарт", який демонструє це.
Деякі компілятори можуть робити щось інше, але ось що говорять стандарти C ++ 03 і 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()
}
Ось приклад програми, яка демонструє, які за замовчуванням вибираються. Я struct
тут використовую s, а не 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