A
Alf P. Steinbach
* Thomas Lorenz:
It probably is.
And with non-polymorphic types you'd get a compile time error.
With polymorphic types, however, the language allows this because the
pointer 'a' might be a pointer to the 'A' subobject of an object of a
class that inherits from both 'A' and 'B':
#include <iostream>
struct A {virtual void print() {std::cout << "A" << std::endl;}};
struct B {virtual void print() {std::cout << "B" << std::endl;}};
struct C: A, B {};
int main()
{
A* a = new C();
B* b = dynamic_cast<B*>( a );
if (b)
b->print();
else
std::cout << "b is 0" << std::endl;
return 0;
}
That's not naive, that's very good.
When you don't know the types at compile time, and a virtual function doesn't
solve the problem (virtual functions perform safe downcasts for you).
Perhaps the most typical example is to apply an event E to an object O, where
you don't know whether O supports event E or not.
In such cases it's preferable to centralize the dynamic casts instead of
having such casts scattered around the code, and one way of centralizing them
is to use the "visitor pattern" (google).
Hello,
first, I didn't find any reference to my question through googling.
dynamic_cast uses RTTI to determine if the cast expression is valid.
Invalid casts of pointers give a '0'-result. As it is the case in the
following example:
-----------------------------------------------------------
#include <iostream>
struct A {virtual void print() {std::cout << "A" << std::endl;}};
struct B {virtual void print() {std::cout << "B" << std::endl;}};
int main(int argc,char* argv[])
{
A* a = new A();
B* b = dynamic_cast<B*>(a);
if (b)
b->print();
else
std::cout << "b is 0" << std::endl;
return 0;
}
-------------------------------------------------------------
This compiles just fine with MS C++ 7, g++ 3.3.3. Running this tells me
(quite correctly) that "b is 0".
What I really don't get is - why isn't this detected at compile time?
It probably is.
And with non-polymorphic types you'd get a compile time error.
With polymorphic types, however, the language allows this because the
pointer 'a' might be a pointer to the 'A' subobject of an object of a
class that inherits from both 'A' and 'B':
#include <iostream>
struct A {virtual void print() {std::cout << "A" << std::endl;}};
struct B {virtual void print() {std::cout << "B" << std::endl;}};
struct C: A, B {};
int main()
{
A* a = new C();
B* b = dynamic_cast<B*>( a );
if (b)
b->print();
else
std::cout << "b is 0" << std::endl;
return 0;
}
OK,
that's what static_cast does (replacing the dynamic_cast with a
static_cast in the example gives a nice compiler error).
Scott Meyers advises to prefer compile time errors to run time errors. So
naive reasoning tells me to prefer static_cast, whenever possible.
That's not naive, that's very good.
So here's the question: Can anybody tell me when to prefer dynamic_cast
to static_cast? Are there any possible situations where static_cast
doesn't really work and you have to use dynamic_cast?
When you don't know the types at compile time, and a virtual function doesn't
solve the problem (virtual functions perform safe downcasts for you).
Perhaps the most typical example is to apply an event E to an object O, where
you don't know whether O supports event E or not.
In such cases it's preferable to centralize the dynamic casts instead of
having such casts scattered around the code, and one way of centralizing them
is to use the "visitor pattern" (google).