Reputation: 1886
The class is polymorphic. Why do both print the same output?
class A
{
public:
virtual void P(){ cout << "A" << endl; }
};
class B : public A
{
public:
void P()override{
cout << "B" << endl;
}
B(){ cout << "Created B" << endl; s = "Created by B"; }
string s;
};
And main: Variant 1:
A* a = new B(); // Created B
B* b = static_cast<B*>(a);
b->P(); B
cout<<b->s<<endl; // Created by B
And variant 2:
A* a = new B();
B* b = dynamic_cast<B*>(a);
if (b){
b->P();
cout << b->s << endl; // Prints same
}
Upvotes: 2
Views: 9348
Reputation:
In this case, static_cast
is semantically equivalent to dynamic_cast
.
static_cast
< new_type > ( expression )2) If new_type is a pointer or reference to some class D and the type of expression is a pointer or reference to its non-virtual base B, static_cast performs a downcast. Such
static_cast
makes no runtime checks to ensure that the object's runtime type is actually D, and may only be used safely if this precondition is guaranteed by other means, such as when implementing static polymorphism. Safe downcast may be done withdynamic_cast
.
dynamic_cast
< new_type > ( expression )5) If expression is a pointer or reference to a polymorphic type
Base
, andnew_type
is a pointer or reference to the typeDerived
a run-time check is performed:a) The most derived object pointed/identified by expression is examined. If, in that object, expression points/refers to a public base of
Derived
, and if only one subobject ofDerived
type is derived from the subobject pointed/identified by expression, then the result of the cast points/refers to thatDerived
subobject. (This is known as a "downcast".)[...]
c) Otherwise, the runtime check fails. If the
dynamic_cast
is used on pointers, the null pointer value of type new_type is returned. If it was used on references, the exceptionstd::bad_cast
is thrown.
The last clause is what makes dynamic_cast
safer, as you can check if the cast was unsuccessful:
Base* b1 = new Base;
if(Derived* d = dynamic_cast<Derived*>(b1))
{
std::cout << "downcast from b1 to d successful\n";
d->name(); // safe to call
}
Upvotes: 1
Reputation: 249123
Both of your examples will do the same thing, and that's fine. Try with this instead:
A* a = new A();
In this case, the static_cast
will "succeed" (though it is undefined behavior), whereas the dynamic_cast
will "fail" (by returning nullptr, which you already check for).
Your original examples don't show anything interesting because they both succeed and are valid casts. The difference with dynamic_cast is that it lets you detect invalid casts.
If you want to know how dynamic_cast
does this, read about RTTI, Run Time Type Information. This is some additional bookkeeping that C++ does in certain cases to inspect the type of an object (it's important for this and also if you use typeid()
).
Upvotes: 8