Conversion from Void* to the Pointer of the Base Class

Conversion from void* to the pointer of the base class

void*'s can only be converted back to their original type. When you store a Derived* in a void*, you can only cast back to Derived*, not Base*.

This is especially noticeable with multiple inheritance, as your derived object might not necessarily be at the same address as your base. If you really need to store things (and retrieve things) with void*, always cast to the base type first, so you have a stable way of getting the object back:

#include <iostream>

struct base { int type; };
struct intruder { int iminyourclassstealingyourbase; };
struct derived : intruder, base {};

int main()
{
derived d; d.type = 5;

void* good = (base*)&d;
void* bad = &d;

base* b1 = (base*)good;
base* b2 = (base*)bad;

std::cout << "good: " << b1->type << "\n";
std::cout << "bad: " << b2->type << "\n";
}

If you then want to go back to the derived type, use a dynamic_cast (or static_cast if you're guaranteed it has to be of the derived type.)

C++: Access violation when casting void* to base class pointer

When Ai derives from B, a pointer to the Ai portion of an object is (usually) not pointing at the same memory address as a pointer to the B portion of the same object (especially if B has data fields in it). Accessing Ai via a B* pointer usually involves pointer fixups, VMT lookups, etc, things that have to be taking into account by the particular compiler being used. That is why you can't simply cast an Ai* pointer to a void* to a B* and expect everything to work correctly. The B* pointer is not a valid B* pointer, it is actually an Ai* pointer that has been reinterpretted as a B*, and that simply does not work legally.

To ensure things stay lined up correctly, you must either:

  • cast Ai* to void*, and then void* to Ai*. Which is what you are trying to avoid.

  • cast Ai* to B* first, and then B* to void*, and then void* to B* (and then optionally B* to Ai* via dynamic_cast if you need to access non-virtual members of Ai).

So, in order for this to work the way you are wanting, do the following when constructing your objects:

void createA1(void** aObj)
{
*aObj = static_cast<B*>(new A1());
}

void createA2(void** aObj)
{
*aObj = static_cast<B*>(new A2());
}

And so on. This ensures that all pointers passed to executeF() are proper B* pointers, and only then can executeF() safely type-cast its received void* pointer to B* and use polymorphism to access whichever derived class it is actually pointing at:

void executeF(void* aPtr, int* result)
{
B* bObjPtr = static_cast<B*>(aPtr);
*result = bObjPtr->f(); // works
}

Update: Alternatively, especially when dealing with multiple derived classes that each have multiple base classes that may or may not all be shared, another option would be to simply wrap the Ai objects in a struct that has an extra field to indicate the object type. Then your create...() functions can return void* pointers to that struct instead of to the Ai objects directly, and the execute...() functions can first cast the void* to that struct, look at its type field, and cast the object pointers accordingly:

enum AType
{
a1, a2 /*, ... */
};

class B
{
public:
virtual ~B() = default;
virtual int f() = 0;
};

class Bx
{
public:
virtual ~B() = default;
virtual int x() = 0;
};

class By
{
public:
virtual ~B() = default;
virtual int y() = 0;
};

// ...

class A1 : public B, public Bx
{
public:
int f() override { return 1; }
int x() override { return 1; }
};

class A2 : public B, public By
{
public:
int f() override { return 2; }
int y() override { return 2; }
};

// ...

struct objDesc
{
AType type;
void *obj;
};

void createA1(void** aObj)
{
objDesc *desc = new objDesc;
desc->type = a1;
desc->obj = new A1();
*aObj = desc;
}

void createA2(void** aObj)
{
objDesc *desc = new objDesc;
desc->type = a2;
desc->obj = new A2();
*aObj = desc;
}

// ...

void destroyObj(void* aObj)
{
objDesc *desc = static_cast<objDesc*>(aObj);
switch (desc->type)
{
case a1:
delete static_cast<A1*>(desc->obj);
break;

case a2:
delete static_cast<A2*>(desc->obj);
break;

//..
}

delete desc;
}

//...

void executeF(void* aPtr, int* result)
{
objDesc *desc = static_cast<objDesc*>(aPtr);
B* bObjPtr = nullptr;

switch (desc->type)
{
case a1:
bObjPtr = static_cast<A1*>(desc->obj);
break;

case a2:
bObjPtr = static_cast<A2*>(desc->obj);
break;

// other classes that implement B ...
}

if (bObjPtr)
*result = bObjPtr->f();
}

void executeX(void* aPtr, int* result)
{
objDesc *desc = static_cast<objDesc*>(aPtr);
Bx* bObjPtr = nullptr;

switch (desc->type)
{
case a1:
bObjPtr = static_cast<A1*>(desc->obj);
break;

// other classes that implement Bx ...
}

if (bObjPtr)
*result = bObjPtr->x();
}

void executeY(void* aPtr, int* result)
{
objDesc *desc = static_cast<objDesc*>(aPtr);
By* bObjPtr = nullptr;

switch (desc->type)
{
case a2:
bObjPtr = static_cast<A2*>(desc->obj);
break;

// other classes that implement By ...
}

if (bObjPtr)
*result = bObjPtr->y();
}

// ...

It is not ideal or flexible, but it will work within the restrictions you have on the other side.

Otherwise, you can replace the struct with a new base class that all other classes must derive from, then you can make use of dynamic_cast as needed:

class Base
{
public:
virtual ~Base() = default;
};

class Bf
{
public:
virtual ~Bf() = default;
virtual int f() = 0;
};

class Bx
{
public:
virtual ~Bx() = default;
virtual int x() = 0;
};

class By
{
public:
virtual ~By() = default;
virtual int y() = 0;
};

class Bz
{
public:
virtual ~Bz() = default;
virtual int z() = 0;
};

class A1 : public Base, public Bf, public Bx
{
public:
int f() override { return 1; }
int x() override { return 1; }
};

class A2 : public Base, public Bf, public By
{
public:
int f() override { return 2; }
int y() override { return 2; }
};

class A3 : public Base, public Bz
{
public:
int z() override { return 3; }
};

// ...

void createA1(void** aObj)
{
*aObj = static_cast<Base*>(new A1());
}

void createA2(void** aObj)
{
*aObj = static_cast<Base*>(new A2());
}

void createA3(void** aObj)
{
*aObj = static_cast<Base*>(new A3());
}

// ...

void destroyObj(void* aObj)
{
delete static_cast<Base*>(aObj);
}

//...

void executeF(void* aPtr, int* result)
{
Base *base = static_cast<Base*>(aPtr);
B* bObjPtr = dynamic_cast<B*>(base);
if (bObjPtr)
*result = bObjPtr->f();
}

void executeX(void* aPtr, int* result)
{
Base *base = static_cast<Base*>(aPtr);
Bx* bObjPtr = dynamic_cast<Bx*>(base);
if (bObjPtr)
*result = bObjPtr->x();
}

void executeY(void* aPtr, int* result)
{
Base *base = static_cast<Base*>(aPtr);
By* bObjPtr = dynamic_cast<By*>(base);
if (bObjPtr)
*result = bObjPtr->y();
}

void executeZ(void* aPtr, int* result)
{
Base *base = static_cast<Base*>(aPtr);
By* bObjPtr = dynamic_cast<Bz*>(base);
if (bObjPtr)
*result = bObjPtr->z();
}

//...

How to send a pointer of an overriden virtual function to the base class?

You can cast the member function pointer to the base class member function pointer type: callfunction(static_cast<void (Base::*)()>(&Derived1::function));. Full example:

class Base
{
protected:
virtual void function() { std::cout << "Base\n"; }
void callfunction(void (Base::* func)()) { (this->*func)(); }
};

class Derived1 : public Base
{
public:
void publicCall() { callfunction(static_cast<void (Base::*)()>(&Derived1::function)); }
private:
void function() override { std::cout << "Derived1\n"; }
};

This is allowed; see cppreference on pointers to member functions:

Pointer to member function of a base class can be implicitly converted to pointer to the same member function of a derived class ...

Conversion in the opposite direction, from a pointer to member function of a derived class to a pointer to member function of an unambiguous non-virtual base class, is allowed with static_cast and explicit cast

In this case, we are converting derived to base rather than vice-versa, so we need to static_cast.


You can avoid requiring the cast from the call-site by casting in Base from a template:

class Base
{
protected:
virtual void function() { std::cout << "Base\n"; }
void callfunction(void (Base::* func)()) { (this->*func)(); }

template <typename Derived, std::enable_if_t<std::is_convertible_v<Derived const*, Base const*>, int> = 0>
void callfunction(void (Derived::* func)()) { callfunction(static_cast<void (Base::*)()>(func)); }
};

class Derived1 : public Base
{
public:
void publicCall() { callfunction(&Derived1::function); }
private:
void function() override { std::cout << "Derived1\n"; }
};

Compiler Explorer link: https://godbolt.org/z/3x8qPK4Tf

How to correctly cast a void* that points to a derived class to a void* that points to a base class at runtime

First, I would suggest using C++ casts, rather than plain old C casts, such as static_cast, reinterpret_cast, dynamic_cast and const_cast. They are safer than the C type casts, since they do only one thing.

Since you mention that you have a pointer to an object of the base/derived class you are trying to cast to, you can use decltype.

decltype is a C++11 specifier that yields the type of the variable passed as argument.

So, you can use something like reinterpret_cast<decltype(base_pointer)>(value).

For further information, have a look at the following resources:

https://en.cppreference.com/w/cpp/language/decltype

Cast a value using decltype, is it possible?

When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?


The discussions in the comments pointed that the initial question asked for a runtime approach, while decltype is compile time. Still, the above might be relevant, so I will add some thoughts on runtime approaches.

The C++ template system and type deduction mechanisms run at compile time. If you want to handle a dynamic type system at runtime (i.e. the user input determining the types used), you have to use something like a factory method.

However, it might be worth considering if there is a better approach to this.

Cast to Base* from void* being any DerivedI*

This shows there is sufficient type information to know where we are in the inheritance hierarchy for any pointer to a virtually Base-derived type.

It most certainly does not. It proves only that "undefined behavior" for your compiler happened to mean "do what you expected." It proves that the implementation you're using gives the virtual base class the same address as the derived class. In this particular case.

As far as the C++ standard is concerned, the only thing you can cast a void* back to is the original type it was when the conversion to void* was made (or to byte-wise pointers like unsigned char*). It doesn't matter if you use reinterpret_cast, C-style casts, or whatever. If the original pointer was a some type, you cannot cast it to the base class.

Well, you can cast it there. But you can't do anything with the pointer except cast it back to void*.

Up-casting the pointer before storing it is not an option either since in my use case for a given object instance, multiple Derived<I> may exist in its hierarchy, making it impossible to down-cast to the right Derived<I>.

Nonsense. The sending code must know what the type is, since it's casting it to a void*. And since it knows what the type is, it must also know what the base type is. So the ways in which this could be a problem are:

  1. if you have multiple base types, and the sending code has no idea which base type the receiving code is using.

  2. if the sending code is a template and doesn't know anything about the type other than the fact that it needs to be sent, yet the receiving code expects a specific base class.

All of these cases effectively mean you have written incoherent code. One of the two parties, sender or receiver, is ignorant of the type that the other party expects. If the sender and receiver can't agree on a type for transmittance, then there is no way for the sender to send it in a way that the receiver can understand it.

Make your code coherent, and the problem goes away.

Safe way to dynamic cast void to a type?

The only thing you can do with a void* pointer is to cast it back to exactly the same type as the pointer that was cast to void* in the first place. The behaviour on doing anything else is undefined.

What you could do in your case is define

class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};

and make this the base class for Alpha and Beta. Then pass a Base* pointer around rather than a void* one, and take your dynamic_casts directly on p.

Note further that if you declared virtual void Speak() = 0; in Base, then your code in main would become simply

int main(){ 
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}

As a rule of thumb, casts of any kind are undesirable.

How conversion of pointer-to-base to void is better than pointer-to-derived to void conversion

The situation where you have to compare different possible source types (A* vs B* in A* -> void* and B* -> void*) can only happen in the context of overload resolution for initialization by user-defined conversion, not in the context of overload resolution for a function call. See also the note at the end of [over.ics.rank]/4.

Here is an example where the quoted phrase is relevant:

struct A {};
struct B : A {};

struct C {
operator A*();
operator B*();
};

int main() {
void* x = C{};
}

Here x is initialized by a conversion function chosen according to [over.match.conv] (see [dcl.init.general]/16.7). All conversion operators converting from C to any type which is convertible to void* by a standard conversion sequence are considered.

Then the best conversion function is chosen according to which of the standard conversion sequences following the conversion function is better (see [over.match.best.general]/2.2).

The phrase you quote tells us that A* -> void* is better than B* -> void*. So the conversion function which will be used here to initialize x is operator A*().

static_cast from Derived* to void* to Base*

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.



Related Topics



Leave a reply



Submit