Question

I would like to cast a pointer to a member of a derived class to void* and from there to a pointer of the base class, like in the example below:

#include <iostream>

class Base
{
    public:
       void function1(){std::cout<<"1"<<std::endl;}
       virtual void function2()=0;
};

class Derived : public Base
{
    public:
       virtual void function2(){std::cout<<"2"<<std::endl;}
};

int main()
{
    Derived d;
    void ptr* = static_cast<void*>(&d);
    Base* baseptr=static_cast<Base*>(ptr);
    baseptr->function1();
    baseptr->function2(); 
}

This compiles and gives the desired result (prints 1 and 2 respectively), but is it guaranteed to work? The description of static_cast I found here: http://en.cppreference.com/w/cpp/language/static_cast only mentions conversion to void* and back to a pointer to the same class (point 10).

Was it helpful?

Solution

In the general case, converting a base to void to derived (or vice versa) via static casting is not safe.

There will be cases where it will almost certainly work: if everything involved is a pod, or standard layout, and only single inheritance is involved, then things should be fine, at least in practice: I do not have chapter and verse from the standard, but the general idea is that the base in that case is guaranteed to be the prefix of the derived, and they will share addresses.

If you want to start seeing this fail, mix in virtual inheritance, multiple inheritance (both virtual and not), and multiple implementation inheritance that are non trivial. Basically when the address of the different type views of this differ, the void cast from and back to a different type is doomed. I have seen this fail in practice, and the fact it can fail (due to changes in your code base far away from the point of casting) is why you want to be careful about always casting to and from void pointer with the exact same type.

OTHER TIPS

In general, no, it is not safe.

Suppose that casting Derived* directly to Base* results in a different address (for example, if multiple inheritance or virtual inheritance is involved).

Now if you inserted a cast to void* in between, how would the compiler know how to convert that void* to an appropriate Base* address?

If you need to cast a Derived* to a void*, you should explicitly cast the void* back to the original Derived* type first. (And from there, the cast from Derived* to Base* is implicit anyway, so you end up with the same number of casts, and thus it's not actually less any convenient.)

From the link you supplied yourself

9) A pointer to member of some class D can be upcast to a pointer to member of its base class B. This static_cast makes no checks to ensure the member actually exists in the runtime type of the pointed-to object.

Meaning as long as you know that the upcast is safe before you do it it is guaranteed to work. That's why you should be using dynamic_cast which returns nullptr if unsuccessful.

Think of it this way if you have.

Type * t1;

static_cast of t1 to one of the classes deriving from it cannot be known at compile time, without in depth analysis of your program (which obviously it is not and should not be doing), so even if it ends up being correct you have no way of checking. dynamic_cast does extra work at runtime to check if the conversion was successful hence the prefix dynamic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top