Hailiang Zhang
Hailiang Zhang

Reputation: 18930

How does static_cast affect the virtual function calls?

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

Answers (4)

lip
lip

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

AnT stands with Russia
AnT stands with Russia

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

Pete Becker
Pete Becker

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

Mark Ransom
Mark Ransom

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

Related Questions