从void *转换为基类的指针

时间:2011-03-26 20:32:05

标签: c++ casting

我有一些层次结构:基础,派生类和一些将用户数据存储为void *的结构。该void可以存储Base和Derived类指针。主要问题是我不知道存储了什么基地或派生指针。


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

如何将void *转换为两个指针的[type]字段? 提前谢谢。

4 个答案:

答案 0 :(得分:18)

void*只能转换回原始类型。当您在Derived*中存储void*时,您只能转回Derived* Base*

这对于多重继承尤为明显,因为派生对象可能不一定与您的基地位于同一地址。如果你真的需要用void*存储东西(并检索东西),总是首先强制转换为基类型,那么你有一个稳定的方法来获取对象:

#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";
}

如果您想返回派生类型,请使用dynamic_cast(或static_cast如果您保证它必须属于派生类型。)

答案 1 :(得分:4)

当你使用多重继承时,结果对象在内部的行为很像复合,概念上是这样的:

struct Derived {
  Base1 b1;
  Base2 b2;
};

您将获得Derived实例的不同地址,具体取决于您是将其强制转换为Base1还是Base2。所以,你不能可靠地做你想做的事。您需要保留指向其中一种相关类型的指针,并使用dynamic_cast

或者,您可以制定自己的规则 - 说您始终将实例的地址存储到特定的基类,并始终返回到此基类。这非常容易出错,我强烈建议您尽可能存储指向公共基类的指针。

答案 2 :(得分:1)

如果您知道它是派生指针并且您想获得基指针,则可以执行以下操作:

Base* d_restored_to_base = (Base*)(Derived*)derived_v;

您会发现Base *指向与Derived *不同的位置,因此需要进行中间演员。

答案 3 :(得分:-2)

使用dynamic_cast,它可以动态地告诉您指针是否指向Base对象。