When is static cast safe when you are using multiple inheritance? - c++

I found myself in a situation where I know what type something is. The Type is one of three (or more) levels of inheritance. I call factory which returns B* however T is either the highest level of a type (if my code knows what it is) or the 2nd level.
Anyways, I did a static_cast in the template which is the wrong thing to do. My question is WHEN can I static cast safely? Is there ever such a time? I did it in this case because I'd rather get compile errors when I accidentally have T as something wacky which (has happened and) dynamic cast ignores (and returns null). However when I know the correct type the pointer is not adjusted causing me to have a bad pointer. I'm not sure why static cast is allowed in this case at all.
When can I use static_cast for down casting safely? Is there ever a situation? Now it seems like it always is wrong to use a static_cast (when the purpose is to down cast)
Ok I figured out how to reproduce it.
#include <iostream>
struct B { virtual void f1(){} };
struct D1 : B {int a;};
struct D2 : B {int a, b; };
struct DD : D1, D2 {};
int main(){
void* cptr = new DD(); //i pass it through a C interface :(
B* a = (B*)cptr;
D2* b = static_cast<D2*>(a); //incorrect ptr
D2* c = dynamic_cast<D2*>(a); //correct ptr
std::cout << a << " " <<b << " " <<c;
}

A cross-cast:
struct Base1 { virtual void f1(); };
struct Base2 { virtual void f2(); };
struct Derived : Base1, Base2 {};
Base1* b1 = new Derived();
Base2* b2 = dynamic_cast<Base2*>(b1);
requires use of dynamic_cast, it cannot be done with static_cast (static_cast should have caused a compile-time error). dynamic_cast will also fail if either base class is not polymorphic (the presence of virtual functions is NOT optional).
See this explanation on MSDN

If Derived has Base as a public (or otherwise accessible) base class, and d is of type Derived*, then static_cast<Base*>(d) is an upcast.
This is always technically safe.
And generally unnecessary, except for cases where you have hiding (shadowing) of method.
Cheers & hth.,

The problem lies with this line:
B* a = (B*)cptr;
If you convert something to a void pointer, you must convert it back to the same type that it was converted from first before doing any other casts. If you have a situation where multiple different types of objects have to go through the same void pointer, then you need to first cast it down to a common type before converting to a void pointer.
int main(){
B *bptr = new DD; // convert to common base first (won't compile in this case)
void* cptr = bptr; // now pass it around as a void pointer
B* a = (B*)cptr; // now back to the type it was converted from
D2* b = static_cast<D2*>(a); // this should be ok now
D2* c = dynamic_cast<D2*>(a); // as well as this
std::cout << a << " " <<b << " " <<c;
}
EDIT:
If you only know that cptr points to some object which is of a type derived from B at the time of the cast, then that isn't enough information to go on. The compiler lets you know that when you try to convert the DD pointer to a B pointer.
What you would have to do is something like this:
int main(){
void* cptr = new DD; // convert to void *
DD* a = (DD*)cptr; // now back to the type it was converted from
D2* b = static_cast<D2*>(a); // this should be ok now, but the cast is unnecessary
D2* c = dynamic_cast<D2*>(a); // as well as this
std::cout << a << " " <<b << " " <<c;
}
but I'm not sure if that is acceptable in your actual usage.

You can safely upcast if you are sure that the object is actually an instance of that class.
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
int main()
{
Base* b = new Derived1;
Derived1* d1 = static_cast<Derived1*>(b); // OK
Derived2* d2 = static_cast<Derived2*>(b); // Run-time error - d isn't an instance of Derived2
}

Just for completeness (knowing that I'm late a little, just for late readers like me...):
static_cast can be applied, if used correctly!
At first, the simple case:
struct D1 { }; // note: no common base class B!
struct D2 { };
struct DD : D1, D2 { };
You can get from D1* to D2* via intermediate downcast to DD*:
D1* d1 = new DD();
D2* d2 = static_cast<DD*>(d1);
The upcast to D2* is implicit then. This is possible even for non-virtual inheritance. But be aware that you need to be 100% sure that d1 really was created as DD when doing the downcast, otherwise you end up in undefined behaviour!
Now the more complex case: Diamond pattern! This is what is presented in the question:
void* cptr = new DD();
B* a = (B*)cptr;
Now this cast is already is dangerous! What actually is implemented here is a reinterpret_cast:
B* a = reinterpret_cast<B*>(cptr);
What you instead want is a simple upcast. Normally, one would not need a cast at all:
B* a = new DD(); //ambigous!
Solely: DD has two inherited instances of B. It would have worked if both D1 and D2 inherited virtually from B (struct D1/2 : virtual B { }; – not to be confused with B/D1/D2 being virtual classes!).
B* b1 = static_cast<D1*>(new DD());
B* b2 = static_cast<D2*>(new DD());
The cast to the respective bases D1 or D2 now makes clear which of the two inherited instances of B shall be pointed to.
You now can get back the respective other instance by down-casting to DD again; due to the diamond pattern, you need an intermediate cast again:
D2* bb1 = static_cast<DD*>(static_cast<D1*>(b1));
D1* bb2 = static_cast<DD*>(static_cast<D2*>(b2));
The very important point about all this matter is: You absolutely need to use, when down-casting, the same diamond edge you used for up-casting!!!
Conclusion: Yes, it is possible using static casts, and it is the only option if the classes involved are not virtual (note: to be differed from virtual inheritance!). But it is just too easy to fail in doing it correctly, sometimes even impossible (e. g. if having stored pointers of base type to arbitrary derived types in a std::vector), so usually, the dynamic_cast solution as presented by Ben is the much safer one (provided virtual data types are available; if so, in the fore-mentioned vector example, it is the only solution!).

A cross cast doesn't need a dynamic_cast at all..
struct Base1 { virtual void f1(); };
struct Base2 { virtual void f2(); };
struct Derived : Base1, Base2 {};
Base1* b1 = new Derived();
// To cast it to a base2 *, cast it first to a derived *
Derived *d = static_cast<Derived *>(b1);
Base2 *b2 = static_cast<Base2 *>(d);

Related

In a diamond inheritance structure, is there a way to cast between the branches?

I have a diamond inheritance structure in my code in which I have a pointer to the
bottom object. I tried to case this to a pointer to the left of the two diamond sides, cast it again to the top of the diamond, and again to the right side. But apparently, C++ kind of remembers the order of casting and things don't work as expected. Example code:
#include <iostream>
class A
{
};
class B1 : public A
{
public:
virtual int Return1() = 0;
};
class B2 : public A
{
public:
virtual int Return2() = 0;
};
class C : public B1, public B2
{
public:
virtual int Return1() { return 1; }
virtual int Return2() { return 2; }
};
int main()
{
C c;
B1* b1 = &c;
A* a = b1;
B2* b2 = (B2*)a;
std::cout << "Return2() = " << b2->Return2();
}
This results in Return2() = 1, so apparently this approach is wrong. I know that something like this works in C#, so my question would be: Is there a way in C++ to do what I'm attempting here or - if not - why is this not an option?
As inheritance is not virtual (for A), you have "Y" inheritance (2 A),
A A
| |
B1 B2
\ /
C
not a diamond (1 A).
Avoid C-cast which might result in reinterpret_cast, and most reinterpret_cast usage leads to Undefined Behavior (UB).
You might use dynamic_cast in your case to have expected behavior (A need to be polymorphic for that, default virtual destructor does the job):
class A
{
public:
virtual ~A() = default; // Added to allow dynamic_cast
};
class B1 : public A
{
public:
virtual int Return1() = 0;
};
class B2 : public A
{
public:
virtual int Return2() = 0;
};
class C : public B1, public B2
{
public:
// override used for extra check from compiler.
int Return1() override { return 1; }
int Return2() override { return 2; }
};
int main()
{
C c;
B1* b1 = &c;
A* a = b1;
B2* b2 = dynamic_cast<B2*>(a); // C-cast replaced by dynamic_cast
assert(b2 != nullptr);
std::cout << "Return2() = " << b2->Return2();
}
Demo
You can see the desired result by changing the last casting to:
B2* b2 = (B2*)&c;
This is an issue related to upcasting and downcasting.
The issue here is that you are using a C cast (T) expr, which is 99% of the time a bad idea in C++.
C casts only exist in C++ due to the need of being retrocompatible with C, and can behave in unexpected ways.
From here:
When the C-style cast expression is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:
a) const_cast<new_type>(expression);
b) static_cast<new_type>(expression), with extensions: pointer or reference to a derived class is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class is inaccessible (that is, this cast ignores the private inheritance specifier). Same applies to casting pointer to member to pointer to member of unambiguous non-virtual base;
c) static_cast (with extensions) followed by const_cast;
d) reinterpret_cast<new_type>(expression);
e) reinterpret_cast followed by const_cast.
The first choice that satisfies the requirements of the respective cast operator is selected, even if it cannot be compiled (see example)
The correct type of cast when downcasting in C++ is dynamic_cast<T>(expr), which checks if the object of the expression can be cast to the derived type T before performing it. If you did that, you would have got a compile time or runtime error, instead of getting a wrong behaviour.
C-style casts never perform dynamic casts, so (B2*) in B2* b2 = (B2*)a becomes equivalent to reinterpret_cast<B2*> which is a type of cast that blindly coerces any pointer type to any other. In this way C++ can't do any of the required pointer "magic" it's usually needed to convert a C* into a valid B2*.
Given that polymorphism in C++ is implemented through virtual dispatching using method tables, and that the pointer in b2 doesn't point to the correct base class (given that it was actually a pointer to B1), you are accessing the vtable for B1 instead of B2 through b2.
Both Return1 and Return2 are the first functions in the vtables of their respective abstract classes, so in your case Return1 is mistakenly called - you could largely approximate virtual invocations with something like b2->vtable[0]() in most implementations. Given that neither of the two methods touch this, nothing breaks and the function returns without crashing the program (which is not guaranteed, given this whole thing is undefined behaviour).

Convert array of pointers of derived class to array of base class pointers

Consider an inheritance hierarchy like this:
A
/ \
B1 B2
\ /
C
|
D
Realized in C++ like so:
class A {
public:
A() {};
virtual ~A() = 0;
double a;
};
A::~A() {};
class B1 : virtual public A {
public:
B1() {}
virtual ~B1() {}
double b1;
};
class B2 : virtual public A {
public:
B2() {}
virtual ~B2() {}
double b2;
};
class C : public B1, public B2 {
public:
C() {}
virtual ~C() {}
double c;
};
class D : public C {
public:
D() {}
virtual ~D() {}
double d;
};
Now, obviously I can do something like this:
D *d = new D();
A *a = (A*) d;
D *d_down = dynamic_cast<D*>(a);
assert(d_down != NULL); //holds
However, I can't seem to figure out how to get same behavior using arrays. Please consider the following code sample to see what I mean by that:
D *d[10];
for (unsigned int i = 0; i < 10; i++) {
d[i] = new D();
}
A **a = (A**) d;
D *d_down = dynamic_cast<D*>(a[0]);
assert(d_down != NULL); //fails!
So my questions would be:
Why does to above assertion fail?
How can I achieve the desired behavior?
I noticed, by chance, that the dynamic_cast above works if I remove the double fields from classes A through D. Why is that?
The problem is, that (A*)d is not numerically equal to d!
See, you have an object like
+---------------------+
| A: vtable ptr A | <----- (A*)d points here!
| double a |
+---------------------+
+---------------------+
| D: | <----- d points here (and so do (C*)d and (B1*)d)!
|+-------------------+|
|| C: ||
||+-----------------+||
||| B1: vptr B1,C,D |||
||| double b1 |||
||+-----------------+||
||+-----------------+|| <----- (B2*)d points here!
||| B2: vptr B2 |||
||| double b2 |||
||+-----------------+||
|| double c ||
|+-------------------+|
| double d |
+---------------------+
When you cast a D* to A*, via static_cast or dynamic_cast, the compiler will inject the necessary arithmetic for you.
But when you cast it via reinterpret_cast, or cast a D** to A**, which is the same thing, the pointer will keep its numeric value, because the cast does not give the compiler the right to dereference the first layer to adjust the second layer.
But then the pointer will still point at D's vtable, not A's vtable, and therefore won't be recognized as A.
Update: I checked the layout in compiler (g++) and the picture should now reflect the actual layout generated in the case in question. It shows that virtual bases live at negative offsets. This is because a virtual base is at different offset depending on the actual type, so it can't be part of the object itself.
The address of object does coincide with address of the first non-virtual base. However, the specification does not guarantee it for objects with virtual methods or bases, so don't rely on it either.
This shows the importance of using appropriate casts. Conversions that can be done implicitly, via static_cast, dynamic_cast or function-style cast are reliable and compiler will inject appropriate adjustments.
However using reinterpret_cast clearly indicates the compiler will not adjust and you are on your own.
A *a = static_cast<A *>(d);
is ok, but
A **aa = static_cast<A **>(&d);
is a compilation error.
The problem with C-style cast is that it does a static_cast when possible and reinterpret_cast otherwise, so you can cross the border to the undefined behavior land without noticing. That's why you shouldn't use C-style cast in C++. Ever.
Note that due to aliasing rules, writing reinterpret_cast essentially always implies Undefined Behavior. And at least GCC does optimize based on aliasing rules. The only exception is cv-(signed/unsigned) char *, which is exempt from strict aliasing. But it only ever makes sense to cast to and from pointers to standard layout types, because you can't rely on layout of objects with bases (any, not just virtual) and/or virtual members.

I can't assign from pointer to pointer to derived class and pointer to pointer to base class? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Conversion between Derived** to Base**
I'm getting back into C++ after several years of mostly Python, and am hitting up against a strongly-typed wall. I think I have a good handle on basic polymorphism and type-casting between pointers of base and derived classes (e.g. Can a pointer of a derived class be type cast to the pointer of its base class?), but here's a stumper: why can't I assign a pointer to a pointer to a derived class to a p-to-p to it's base class?
For more context (and perhaps tips on doing this less pythonishly), here's a reduced version of what I'm trying to do. I want to have a list of pointers to objects (derived from a single class) and a string identifying them (i.e. a map<string, obj*>). A set of components will then pass a list of identifying strings and locations to store a pointer to the corresponding object (i.e. a map<string, obj**>). I should then be able to find the appropriate object by its string id, and fill in the appropriate pointer for subsequent use by the component.
Simplified code to do this is
#include <map>
#include <string>
using namespace std;
class base
{
};
class derived: public base
{
};
typedef map<string, base**> BasePtrDict;
typedef map<string, base*> BaseDict;
int main(int argc, char* argv[])
{
base b1, b2;
derived d;
derived* d_ptr;
BaseDict base_dict;
base_dict["b1"] = &b1;
base_dict.insert(make_pair("b2",&b2)); // alternate syntax
base_dict["d"]= &d;
BasePtrDict ptr_dict;
ptr_dict["d"] = &d_ptr;
for (auto b = ptr_dict.begin(); b != ptr_dict.end(); b++)
*(b->second) = base_dict[b->first];
return 0;
}
This runs into a compile error at ptr_dict["d"] = &d_ptr;. Why? In the C++ paradigm, what should I be doing? Do I really need to do ugly (unsafe?) reinterpret_cast<base>() everywhere?
You're losing the necessary information to be able to cast a base * to a derived *.
Consider the case where derived inherits from multiple base classes, so a cast needs to adjust the pointer value. Then derived *pd = static_cast<derived *>(pb) for a pointer-to-base pb will automatically apply the pointer adjustment.
However derived *pd; base **ppb = &pd; *ppb = *pb will fail to apply the pointer adjustment, so this cannot be legal.
What you should be doing is:
base *b_ptr;
... // existing code
derived *d_ptr = static_cast<derived *>(b_ptr);
Consider what would be enabled if it were permitted to treat a derived** as a base**:
class base
{
};
class derived: public base
{
public:
int boom;
}
void light_the_fuse( base** pb)
{
*pb = new base;
}
int main()
{
derived* pd = NULL;
light_the_fuse( &pd);
pd->boom = 42; // uh oh, `pd` points to a `class base`...
return 0;
}
In order to do a child-to-base conversion the types need to be related. For derived** to base** this implies that derived* is a child of base* which is clearly not true as they're orthogonal pointer types (that happen to point to related classes).
You should be able to solve this with a static_cast rather than reinterpret_cast though:
ptr_dict["d"] = &static_cast<base*&>(d_ptr);
The direct cast derived* to base* is ok, but that's not what you're attempting. You're attempting to do derived** to base**, which isn't an implicit cast. That aside, may I ask why? I'd even go ahead and ask whether you actually need pointers, but double pointers?
It will be much simpler to replace
derived* d_ptr;
with
base* d_ptr;
and use a cast anytime when you may need to apply the exact type of d_ptr but of course the principles of object orientation say that such a case should be quite rare.
You cannot and should not assign a Derived** to a Base** because it is unsafe. If the cast was permitted, then it would allow Derived* to point to types that are not Dervied types. Consider the following:
class Base {};
class Derived: public Base {};
class Other: public Base {};
...
Derived derived;
Derived* derived_p = &derived; // derived_p points to derived.
Derived** derived_pp = &derived_p; // derived_p points to derived.
// derived_pp points to derived_p.
Base** base_pp = derived_pp; // derived_p points to derived.
// base_pp points to derived_p.
Other other;
Other* other_p = &other; // other_p points to other.
*bpp = op; // base_pp points to derived_p.
// derived_p points to other.
If the above code was valid, it would allow Derived* derived = new Other().
Unfortunately, I am not exactly sure what is trying to be accomplished, so I cannot provide an alternative solution.
This is almost similar to Why do I need a reinterpret_cast to convert Fred ** const to void ** const?
Pointer to two different object types are basically incompatible. But, there are exceptions
Derived* to Base*... Derived and Base are related and therefore, conversion is allowed (after typecasting to Base*, the pointer would actually be pointing to an object of Base type
T* to void* - allowed (see the link above)
but there is no reason why D** should be allowed to be converted to B**, because B* and D* are essentially different types.

Multiple inheritance pointer comparison

I have a class Derived that inherits directly from two base classes, Base1 and Base2. I'd like to know if it's safe, in general, to compare pointers to the base classes to determine if they are the same Derived object:
Base1* p1;
Base2* p2;
/*
* Stuff happens here. p1 and p2 now point to valid objects of either their
* base type or Derived
*/
//assert(p1 == p2); //This is illegal
assert(p1 == static_cast<Base1*>(p2)); //Is this ok?
assert(static_cast<Derived*>(p1) == static_cast<Derived*>(p2)); //How about this?
The pointers are guaranteed to be valid, but not necessarily to point to a Derived object. My guess is that this is probably fine, but I wanted to know if it was ok from a technical C++ perspective. I actually never do any operations on the pointers, I just want to know if they point to the same object.
EDIT: It seems to be safe if I can guarantee that p1 and p2 point to Derrived objects. I basically want to know if it is safe if they don't- if one or both point to a base object, will the comparison necessarily fail? Again, I can guarantee the pointers are valid (i.e., p1 would never point at a Base2 object or vice versa)
Well, no, it won't work.
I'm personally a big fan of learning-by-example, so here's one:
#include <iostream>
class Base1
{
public:
Base1()
{
numberBase1 = 1;
}
int numberBase1;
};
class Base2
{
public:
Base2()
{
numberBase2 = 2;
}
int numberBase2;
};
class Derived : public Base1, public Base2
{
public:
Derived()
{
numberDerived = 3;
}
int numberDerived;
};
int main()
{
Derived d;
Base1 *b1 = &d;
Base2 *b2 = &d;
std::cout << "d: " << &d << ", b1: " << b1 << ", b2: " << b2 << ", d.numberDerived: " << &(d.numberDerived) << std::endl;
return 0;
}
One run-through on my computer outputted this:
d: 0035F9FC, b1: 0035F9FC, b2: 0035FA00, d.numberDerived: 0035FA04
Soo.. If we define the address of d as 0, then b1 is 0, b2 is +4 and the number of d is +8. This is because an int on my machine is 4 byte long.
Basically, you have to look at the layout of how C++ internally represents a class:
Address: Class:
0 Base1
4 Base2
8 Derived
.. So in total, instantiating a Derived class will allocate space for the base classes of the derived class, and finally make room for the derived object itself. Since we have 3 integers here, that'll be 12 bytes.
Now, what you're asking (unless I misunderstood something) is if you can compare the address of the different base class pointers to each other to see if they point to the same object, and the answer is no - Not directly at least, as in my example, b1 would point to 0035F9FC, while b2 would point to 0035FA00. In C++, this offsetting is all done at compile time.
You could probably do some magic with RIIA and sizeof() and determine how much of an offset b2 should have to be comparable to b1, but then you run into all kinds of other trouble like virtuals. In short, I would not recommend this approach.
A much better way would be to cast to Derived* like ialiashkevich said, however, that would impose a problem if your object was not an instance of Derived*.
(Disclaimer; I haven't used C++ in 3-4 years, so I might be a bit off my game. Be gentle :) )
Casting to Derived* before comparison is the right way to go.
There is a similar topic: C++ pointer multi-inheritance fun
Well, turns out the shortest way to achieve what you're looking for is:
assert(dynamic_cast<void*>(p1) == dynamic_cast<void*>(p2));
Dynamically casting to void* effectively down-casts the given pointer to its most derived class, so you're guaranteed if both point on the same object, the assert won't fail.
Indeed, there are practical uses for dynamic-casting to void pointer...
Edit: to answer the question's edit, the comparison is not safe. Consider the following code:
Base2 b2;
Base1 b1;
assert(static_cast<Derived*>(&b1) == static_cast<Derived*>(&b2)); // succeeds!
The memory layout of the two different bases is similar to that of a Derived (on a common implementation - the stack grows opposite of the heap). The first static_cast leaves the pointer as is, but the second one moves the pointer sizeof(Base1) back, so now they both point on &b1, and the assert succeeds - even though the objects are different.
You should use static_cast only if you know for sure the cast is correct. This is not your case, so you must use dynamic_cast, possibly as suggested above.
The short answer is no, this is generally not a good idea.
NOTE: This is assuming you want custom equivalence for all of your classes, if you want to check if they are the same object, it is better to do (Derived *).
A much better solution would be to overload the == operator for Base1, Base2, and Derived.
Assuming Base1 has 1 parameter param1 for equality and Base2 has another parameter param2 for equality:
virtual bool Base1::operator==(object& other){
return false;
}
virtual bool Base1::operator==(Base1& other)
{
return this.param1 == other.param1;
}
virtual bool Base2::operator==(object& other){
return false;
}
virtual bool Base2::operator==(Base2& other)
{
return this.param2 == other.param2;
}
virtual bool Derived::operator==(object& other){
return false;
}
virtual bool Derived::operator==(Derived& other){
return this.param1 == other.param1 && this.param2 == other.param2;
}
virtual bool Derived::operator==(Base1& other){
return this.param1 == other.param1;
}
virtual bool Derived::operator==(Base2& other){
return this.param2 == other.param2;
}
It appears to be invalid, based on this SO question:
How is C++'s multiple inheritance implemented?
Basically, because of the way the objects are laid out in memory, a cast to either Base1* or Base2* results in a mutation of the pointer that I can't arbitrarily reverse at runtime without a dynamic_cast, which I'd like to avoid. Thanks everyone!
Use dynamic_cast, and watch out for NULL.
#include <cassert>
struct Base1 { virtual ~Base1() {} };
struct Base2 { virtual ~Base2() {} };
struct Derived : Base1, Base2 {};
bool IsEqual(Base1 *p1, Base2 *p2) {
Derived *d1 = dynamic_cast<Derived*>(p1);
Derived *d2 = dynamic_cast<Derived*>(p2);
if( !d1 || !d2 ) return false;
return d1 == d2;
}
int main () {
Derived d;
Base1 *p1 = &d;
Base2 *p2 = &d;
Base1 b1;
Base2 b2;
assert(IsEqual(p1, p2));
assert(!IsEqual(p1, &b2));
assert(!IsEqual(&b1, p2));
assert(!IsEqual(&b1, &b2));
}
assert(p1 == p2); //This is illegal
assert(p1 == static_cast<Base1*>(p2)); //Is this ok?
assert(static_cast<Derived*>(p1)
== static_cast<Derived*>(p2)); //How about this?
None of them is a good solution. The first one will not compile, as you cannot compare pointers of unrelated types. The second one will not compile either (unless Base1 and Base2 are related through inheritance) for the same reason: you cannot static_cast to a pointer of an unrelated type.
The third option is borderline. That is, it is not correct, but it will work in many cases (as long as inheritance is not virtual).
The proper way of comparing for identity would be using dynamic_cast to the derived type and checking for null:
{
Derived *tmp = dynamic_cast<Derived*>(p1);
assert( tmp && tmp == dynamic_cast<Derived*>(p2) );
{

Conversion from void* to the pointer of the base class

I have some hierarchy: base, derived classes and some structure storing user data as void*. That void can store both Base and Derived classes pointers. Main problem that I do not know what is stored there base or derived pointer.
class Base
{
public:
int type;
};
class Derived: public Base
{};
Base* base;//init base pointer
Derived* derived;//init derived pointer
void* base_v = base;
void* derived_v = derived;
//void pointers are correct. They point to base and derived variables.
//try to get type field after converting pointers back
Derived* d_restored = (Derived*)derived_v;//d_restored correct
Base* b_restored = (Base*)base_v;//b_restored correct
Base* d_restored_to_base = (Base*)derived_v;// INCORRECT
How to convert void* to get [type] field for both pointers?
Thanks in advance.
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.)
When you use multiple inheritance, the resulting object is internally acting much like a composite, conceptually something like this:
struct Derived {
Base1 b1;
Base2 b2;
};
You will get different addresses for your instance of Derived depending on whether you cast it to Base1 or Base2. So, you can't reliably do what you want to do. You'll need to keep a pointer to one of the involved types, and use dynamic_cast
Alternatively, you could make your own rules - saying that you always store the address of your instance casted to a specific base class, and always cast back to this base class. This is very error-prone, and I'd strongly recommend that you try to store a pointer to a common base class if at all possible.
If you know it's a derived pointer and you want to get a base pointer, you can do this:
Base* d_restored_to_base = (Base*)(Derived*)derived_v;
You will find that the Base* points to a different location than the Derived*, so the intermediary cast is required.
Use dynamic_cast, it can dynamically tell you if the pointer points to a Base object or not.