Reputation: 18930
I have the following code (stolen from virtual functions and static_cast):
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
virtual void foo() { std::cout << "Derived::foo() \n"; }
};
If I have:
int main()
{
Base base;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
The print-out will be: Base::foo()
However, if I have:
int main()
{
Base * base;
Derived* _1 = static_cast<Derived*>(base);
_1->foo();
}
The print-out will be: Segmentation fault: 11
Honestly, I don't quite understand both. Can somebody explain the complications between static_cast and virtual methods based on the above examples? BTW, what could I do if I want the print-out to be "Derived::foo()
"?
Upvotes: 1
Views: 3120
Reputation: 688
In your second example, you segfault because you did not instanciate your base pointer. So there is no v-table to call. Try:
Base * base = new Base();
Derived* _1 = static_cast<Derived*>(base);
_1->foo();
This will print Base::foo()
The question makes no sense, as the static_cast will not affect the v-table. However, this makes more sens with non-virtual functions :
class Base
{
public:
void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
void foo() { std::cout << "Derived::foo() \n"; }
};
int main()
{
Base base;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
This one will output Derived::foo(). This is however a very wrong code, and though it compiles, the behavior is undefined.
Upvotes: 5
Reputation: 320631
A valid static_cast
to pointer or reference type does not affect virtual calls at all. Virtual calls are resolved in accordance with the dynamic type of the object. static_cast
to pointer or reference does not change the dynamic type of the actual object.
The output you observe in your examples is irrelevant though. The examples are simply broken.
The first one makes an invalid static_cast
. You are not allowed to cast Base &
to Derived &
in situations when the underlying object is not Derived
. Any attempt to perform such cast produces undefined behavior.
Here's an example of valid application of static_cast
for reference type downcasting
int main()
{
Derived derived;
Base &base = derived;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
In your second example the code is completely broken for reasons that have nothing to do with any casts or virtual calls. The code attempts to manipulate non-initialized pointers - the behavior is undefined.
Upvotes: 6
Reputation: 76438
In both examples the behavior is undefined. A Base
object is not a Derived
object, and telling the compiler to pretend that it is doesn't make it one. The way to get the code to print out "Derived::foo()"
is to use an object of type Derived
.
Upvotes: 2
Reputation: 308402
The whole purpose of virtual functions is that the static type of the variable shouldn't matter. The compiler will look up the actual implementation for the object itself (usually with a vtable pointer hidden within the object). static_cast
should have no effect.
Upvotes: 2