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.
Related
I'm having real trouble to figure out this casting problem. Starting with 3 classes:
#include <vector>
// Pure virtual class
class Base1{
public:
virtual ~Base1();
virtual void do_sth()=0;
}
class Base2{
public:
int prop=3;
~Base2();
}
class Derived: public Base1, Base2{
~Derived();
void do_sth(){print("Hi");};
}
How can I perform the following conversion?
std::vector<Base1*> vec1
vec1.reserve(10);
for( int i = 0; i < 10; ++i )
vec1.push_back(new Derived());
// To this type...?
std::vector<Base2*> vec2 = ?????;
Some remarks:
I'd use dynamic_cast to perform safe casting from Base1 to Derived.
Ideally, no object copies are made in the process!.
My best bet so far is to call vec2.data() to obtain a Base1* pointer, then dynamic_cast to Derived, then static cast to Base2, but I don't know how to transfer memory ownership nor how to pass vector size.
The comments to the question have gotten rather muddled, so I'll post this partial answer here, rather than trying to straighten out the comments.
Base1 has a virtual function. Good start.
Derived is derived from Base1.
Derived is also derived from Base2.
If you have an object of type Derived you can create a pointer to Base1 that points at the derived object:
Derived d;
Base1* b1 = &d;
Now that you have a pointer to a polymorphic base class, you can use dynamic_cast to perform a cross-cast:
Base2* b2 = dynamic_cast<Base2*>(b1);
The compiler knows how to do that, and the result should be the same pointer value as you'd have gotten if you did it directly:
Base2* b2x = &d;
assert(b2x == b2);
Note, too, that since the code traffics in vectors of pointers, it seems that the Derived objects are being created with new Derived. If that's the case, and eventually the code deletes the Derived object through a pointer to one of the base types, then the base type must have a virtual destructor.
There are no Derived objects in vec1 nor vec2, so you can't get pointers to other base subobjects of a Derived from an element of either.
If pass a Derived to vec1.push_back, it will copy-construct a Base1 from the Base1 subobject of the Derived. This is called object slicing.
If you have a vector of pointers (raw or smart) to Base1 in vec1, then those could point to the Base1 base subobject of a Derived, at which point you can dynamic_cast<Base2*> them, which will in general give you a different pointer value.
I wanted to know if it's possible to get the original type of an object when held through a pointer to base class.
For example:
class Base {
virtual void f() = 0
};
class Derived: public Base {};
Base * ptr=new Derived;
//if I use
cout << typeid(ptr).name(); //prints Base*
I want it to print the original type "Derived". Is there a way to do it?
Yes, the static and dynamic type of ptr are both Base *. However, for *ptr, the situation is different. The static type is Base &, but the dynamic type is Derived &. So that's what you want to test:
cout << typeid(*ptr).name();
You can try with dynamic_cast
if(Derived* d = dynamic_cast<Derived*>(b1))
{
std::cout << "downcast from b1 to d successful\n";
d->name(); // safe to call
}
Be careful as this is often seen as a bad practice, and you shouldn't really do it. You don't need the derived type class, try to think in terms of interfaces.
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.
Here is my test example:
struct base {
virtual ~base(){}
int x;
};
struct derived: public virtual base {
base * clone() {
return new derived;
}
derived(): s("a") {}
std::string s;
};
int main () {
derived d;
base * b = d.clone();
derived * t = reinterpret_cast<derived*>(b);
std::cout << t->s << std::endl;
return 0;
}
It crashes at the line where I print s. Since "b" is a pointer to the derived class, reinterpret_cast should just work. I wonder why it crashes. At the same time, if I replace reinterpret_cast with dynamic_cast, then it works.
Even if b is here dynamically of type derived, you have to use dynamic_cast. This is what dynamic_cast is for, to dynamically convert a pointer of a base class into a derived class at runtime.
reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.
Don't reinterpret_cast it, it will cause trouble with multiple or virtual inheritance, like in your case. Wont a simply static_cast do the job here?
To know why, search for implementations of virtual inheritance. A common one is to store a pointer to the base class within the object, so the virtual base does not share the same address than its derived classes. There is a similar case when multiple inheritance is used.
In short, reinterpret_cast can't do much more than casting pointers to ints and back (if there is enough size in the int to contain a pointer).
As the other answers here suggested, you cannot use reinterpret_cast in this fashion because the value of the pointer to base actually differs from the value of the pointer to derived. The valid pointer is deduced at runtime which is why you have to use dynamic_cast. static_cast cannot work, as you don't know at designtime through which intermediate type the most derived class (the one you want to cast to) was derived from the type you have a pointer to.
The real question here should be: I know at design time, how to compute the derived pointer from the base pointer. How can the runtime penalty (of dynamic_cast) be avoided?
Frankly, I don't see a really good option here, but a possible option is to store the pointer to the most derived type in a constant pointer inside the root class, like so:
struct base {
void* const self;
virtual ~base() {}
protected:
base(void* self) : self(self) {}
};
struct derived : public virtual base {
derived() : base(this) {}
}
This is ugly and dangerous, because it sacrifices type safety for performance (if you are really lucky, you get a slight runtime performance out of it). But you will be able to reinterpret_cast your base pointer (the self member of type void*) into a derived pointer.
I need to use dynamic cast void*
void *target = (MYClass*)target;//I am storing initially(to implment delegate mechanism)
....
delegateClass *delegate = dynamic_cast<delegateClass*>(target);
It is giving error cannot convert void*, I cannot use below code... since it is a delegate mechanism
delegateClass *delegate = dynamic_cast<delegateClass*>(((MYClass*))target);
How to get the type of target and implement... If i use typeid() i can get the name of the class but how to use typeid in the above equation instead of (((MYClass*))target).
You cannot use dynamic cast unless the original type of the variable had a vtable (ie, had virtual functions). This is because dynamic_cast requires run-time type information, which is recorded in the vtable; if the vtable is missing, the compiler doesn't know what type the object is.
You should declare a base class with a virtual destructor, and use pointers to this base class rather than void *.
If you must pass the object as a void * then you should use
delegateClass *delegate = static_cast<delegateClass*>(((MYClass*))target);
as there is no class relationship between the void *target and delegateClass. Here you are saying that you know that target _is_a_ delegateClass.
However this idiom is usually used for passing code through standard C interfaces and back.
I'm in a similar situation and being learning c++ style type casting. I referred to this llink http://www.cplusplus.com/doc/tutorial/typecasting/
From this what I can interpret is that the purpose of dynamic_cast is to ensure that the result of the type conversion is a valid complete object of the requested class. So when we try to convert from derived class to base class the conversion is smooth. But the vice versa is not true.
class CBase { };
class CDerived: public CBase { };
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived
Now for that to work the base class should be polymorphic i.e. it should have a virtual function. When a class is polymorphic, dynamic_cast performs a special checking during runtime to ensure that the expression yields a valid complete object of the requested class. Have a look here.
class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };
int main () {
try {
CBase * pba = new CDerived;
CBase * pbb = new CBase;
CDerived * pd;
pd = dynamic_cast<CDerived*>(pba);
if (pd==0) cout << "Null pointer on first type-cast" << endl;
pd = dynamic_cast<CDerived*>(pbb);
if (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
}
Here the code tries to perform two dynamic casts from pointer objects of type CBase* (pba and pbb) to a pointer object of type CDerived*, but only the first one is successful. Even though both are pointers of type CBase*, pba points to an object of type CDerived, while pbb points to an object of type CBase. Thus, when their respective type-castings are performed using dynamic_cast, pba is pointing to a full object of class CDerived, whereas pbb is pointing to an object of class CBase, which is an incomplete object of class CDerived so it returns a null pointer to indicate the failure.
So I'd suggest you to make use of the static_cast which offers bi directional type casting i.e. from derived to base class and also from derived to base class. But in that case programmer needs to ensure that the conversion is safe becasue the type checking is not performed at run time as in case of dynamic_cast.
In your code here either make target to point to deligate class object before conversion(but make sure Myclass is polymorphic) otherwise you can go for static_cast.
This explaination is based on my very recent reading on the topic and I'd suggest you to refer to Effective C++ for more insight about this. I hope this will help. :)