Wirtualne mogą mieć wartości domyślne. Wartości domyślne w klasie bazowej nie są dziedziczone przez klasy pochodne.
To, która wartość domyślna jest używana - tj. Klasa bazowa „czy klasa pochodna” - jest określane przez typ statyczny użyty do wywołania funkcji. Jeśli wywołujesz za pośrednictwem obiektu klasy bazowej, wskaźnika lub odwołania, używana jest wartość domyślna oznaczona w klasie bazowej. I odwrotnie, jeśli wywołujesz za pośrednictwem obiektu klasy pochodnej, używany jest wskaźnik lub odwołanie, wartości domyślne oznaczone w klasie pochodnej. Pokazuje to przykład poniżej standardowego cytatu.
Niektóre kompilatory mogą zrobić coś innego, ale tak mówią standardy C ++ 03 i C ++ 11:
8.3.6.10:
Wywołanie funkcji wirtualnej (10.3) wykorzystuje domyślne argumenty w deklaracji funkcji wirtualnej określone przez statyczny typ wskaźnika lub referencji oznaczającej obiekt. Funkcja przesłaniająca w klasie pochodnej nie pobiera argumentów domyślnych z funkcji, którą przesłania. Przykład:
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()
}
Oto przykładowy program pokazujący, jakie ustawienia domyślne są pobierane. Używam struct
tutaj znaków s zamiast class
es po prostu dla zwięzłości - class
i struct
są one dokładnie takie same pod każdym względem, z wyjątkiem domyślnej widoczności.
#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;
}
Dane wyjściowe tego programu (na MSVC10 i GCC 4.4) to:
Base 42
Der 42
Der 84