<1> The first two sentences are correct. dynamic_cast needs a class to be polymorphic. It also is generally more expensive. The rest, though....
sizeof() has absolutely nothing to do with how the cast behaves or whether or not it's safe/successful.
Also, static_cast will fail unless the types are related. Example:
1 2 3 4 5
|
class A {};
class B {};
A* a = new A;
B* b = static_cast<B*>(a); // compiler error, A and B are not related
|
<2> This is false. The only time you should "always" use static_cast is if you know for a fact the cast will be safe. Again whether or not it's "safe" has nothing to do with the sizeof() the class. See notes at the bottom.
<3> This is false. static_cast will correctly adjust the vtable as needed.
<4> N/A, there is no issue in <3>.
Really, you are way overcomplicating things here. static_cast and dynamic_cast are quite simple. They are actually
identical except for the below key points:
1) dynamic_cast does a runtime check to make sure the cast is good. This means it's generally slower.
2) Also, because dynamic_cast does the runtime check, it's much safer. There is zero risk of a bad cast going unnoticed.
3) dynamic_cast requires the class to be polymorphic. static_cast does not.
The only difference is the runtime check. But both casts cast the pointer the same way.
As for what a bad cast is...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
class Parent
{
public:
virtual ~Parent() {} // make it polymorphic
};
class A : public Parent { };
class B : public Parent { };
int main()
{
A a;
B b;
Parent* p = &a; // p points to an 'A' object
// how dynamic cast works:
A* dyn_a = dynamic_cast<A*>(p); // dynamic_cast checks 'p' to make sure it points to an 'A'
// it does, so this cast is safe. dynamic_cast succeeds.
B* dyn_b = dynamic_cast<B*>(p); // dynamic_cast checks 'p'. It will see that 'p' does not
// point to a 'B', so this is a bad cast. dynamic_cast will fail and dyn_b will be == nullptr
// how static_cast works
A* sta_a = static_cast<A*>(p); // static_cast assumes the cast is good. No runtime check
// sta_a will be identical to dyn_a above
B* sta_b = static_cast<B*>(p); // static_cast assumes the cast is good... BUT IT ISN'T
// 'p' does not point to a 'B', so this is a bad cast! static_cast succeeds, resulting in
// 'sta_b' being a BAD POINTER. Dereferencing sta_b has undefined behavior.
}
|
That's the difference.
Really... this means that when you have to downcast:
- use static_cast only if you are 100% sure the cast is good.
- use dynamic_cast if you are not sure.