Reputation: 1474
I am trying to figure out what happens when you dynamic_cast
from one derived class to another derived class. Why does the below code raise a segmentation fault? Note that I am not trying to use this code for anything. I merely want to understand what is happening.
It's also worth noting that the same code works using static_cast
. I can't seem to find any documentation that goes into the finer details of what is happening here. Can somebody explain?
struct base
{
virtual void printing(){cout<<"base printing"<<endl;};
};
struct derived_1 :public base
{
virtual void printing(){cout<<"derived_1 printing"<<endl;};
};
struct derived_2 :public base
{
virtual void printing(){cout<<"derived_2 printing"<<endl;};
};
int main()
{
base * b = new derived_2();
derived_1 *d_1 = dynamic_cast<derived_1*>(b);
// calling printing raises segmentation fault
d_1->printing();
}
Upvotes: 1
Views: 1257
Reputation: 4679
The cast to derived_1
will fail, because derived_2
is a base
object but not a derived_1
object. Therefore, you cannot "side cast" to the desired pointer type.
Not that whenever dynamic_cast
fails, it will return a nullptr
(except for reference types). This eventually leads to the segmentation fault in your code (in general, I would suggest you always add a if (d_1 != nullptr)
before using a dynamically casted object).
Update:
By the way, this is actually a good example for the necessity of dynamic_cast
. Even though you could be tempted to use static_cast
in your example and it would compile, you will be dealing with undefined behavior. Using static_cast
will compile without hickups, but you would actually be working with a broken type. Assume derived_1::printing()
accesses some variable derived_1::a
, which does not exist in derived_2
. By statically side-casting a derived_2
object (which doesn't have a
) to a derived_1
object d_1
, you would falsely assume d_1
to contain some valid a
, which is not the case.
Example:
// ...
struct derived_1 :public base
{
const int a = 123;
void printing() override {cout<<"derived_1 printing " << endl;}
void foo() { cout << "Foo using constant = " << a << endl; }
};
// ...
int main()
{
base * b = new derived_2();
derived_1 *d_1 = static_cast<derived_1*>(b);
d_1->printing(); // Will call derived_2::printing(), which is not what you expect!
d_1->foo(); // Won't show a = 123 but some nonesense (mostly 0),
// because a is not defined in derived_2.
}
Upvotes: 1