C++ polymorphism and default argument
I have these classes:
class Base
{
public:
virtual void foo(int x = 0)
{
printf("X = %d", x);
}
};
class Derived : public Base
{
public:
virtual void foo(int x = 1)
{
printf("X = %d", x);
}
};
When I have:
Base* bar = new Derived();
bar->foo();
My output is "X = 0", even if foo is called from Derived, but when I have:
Derived* bar = new Derived();
bar->foo();
My output is "X = 1". Is this be开发者_Go百科havior correct? (To select default parameter value from the declaration type, instead of selecting it from actual object type). Does this break C++ polymorphism?
It can cause many problems if somebody uses virtual functions without specifying the actual function parameter and uses the function's default parameter.
Default arguments are retained even if you override a function! And this behaviour is correct. Let me search the reference from the C++ Standard.
§8.3.6/10 [Default arguments] from the C++ Standard says,
A virtual function call (10.3) uses the default arguments in the declaration of the virtual function determined by the static type of the pointer or reference denoting the object. An overriding function in a derived class does not acquire default arguments from the function it overrides.
The example from the Standard itself
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()
}
Also, not only it's retained, it is evaluated everytime the function is called:
§8.3.6/9 says,
Default arguments are evaluated each time the function is called
The behavior is correct. Check out the answer to this question for an explanation:
Can virtual functions have default parameters?
Moral: treat default parameter values as part of the function signature and do not modify them when overriding virtual functions!
This is what C++ designed, I think.
The polymorphism is finished by virtual table, which internally plays with pointer to functions, but the parameter's default value is not stored with the function pointer, it is binded in compiling phase, so it can only get the default value by first looking at its type, in your first case, it is Base, then it use 0 as the default value.
精彩评论