Conversion from void* to the pointer of the base class

橙三吉。 提交于 2019-12-28 05:46:46

问题


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.


回答1:


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.)




回答2:


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.




回答3:


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.




回答4:


Use dynamic_cast, it can dynamically tell you if the pointer points to a Base object or not.



来源:https://stackoverflow.com/questions/5445105/conversion-from-void-to-the-pointer-of-the-base-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!