问题
struct B {
virtual void foo ()
{ cout << "B::foo()\n"; }
};
struct D : B {
void foo () //final
{ cout << "D::foo()\n"; }
};
int main ()
{
B *pB = new B;
D *pD = static_cast<D*>(pB);
pB->foo();
pD->foo();
}
Outputs expected behavior:
B::foo()
B::foo()
If we make the D::foo()
final, then the output is pleasantly different:
B::foo()
D::foo()
Which means that virtual
functionality is not kicked-in when the method is invoked with pointer/reference of a class which has that method declared as final
.
Also it means that, final
isn't just a compile-time check but also contributes to runtime behavior.
Is it a standard behavior for all compilers. I have tested with g++4.7.
Edit:
Spawned a new question with clarification. Closing this question.
回答1:
D *pD = static_cast<D*>(pB);
With this statement, you gave up the right to having sane program behavior. C++ does not require this operation to work if what static_cast
is given is not actually of type D
or one of D
's derived classes (which it isn't).
So it's not optimizations that are thwarting you, just bad code.
There's a reason why dynamic_cast
exists; a proper dynamic_cast
would have quickly failed on this, returning nullptr
for an illegal cast.
回答2:
You're entering the realm of undefined behaviour since you're accessing an object through a pointer / reference to a type that is not the actual type of the object.
3.10 [basic.lval] p10
If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
- the dynamic type of the object
- [...]
The dynamic type of pB
is Base*
, obviously, but the dynamic type of pD
is still Base*
.
回答3:
You're invoking undefined behavior here. You can't just downcast a pointer arbitrarily.
来源:https://stackoverflow.com/questions/13170189/compiler-added-optimization-causes-different-behavior-for-final-methods