从void*到基类指针的转换

问题描述 投票:0回答:4

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

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] 字段? 预先感谢。

c++ casting
4个回答
24
投票

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

这在多重继承中尤其明显,因为派生对象可能不一定与基址位于同一地址。如果您确实需要使用

void*
存储内容(并检索内容),请先将 always 转换为基本类型,这样您就有了一种稳定的方式来获取对象:

#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
,如果您保证它必须是派生类型。)


4
投票

当您使用多重继承时,生成的对象在内部的行为非常类似于复合体,概念上类似于:

struct Derived {
  Base1 b1;
  Base2 b2;
};

您将获得 Derived 实例的不同地址,具体取决于您将其转换为 Base1 还是 Base2。所以,你无法可靠地做你想做的事。您需要保留指向所涉及类型之一的指针,并使用

dynamic_cast

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


1
投票

如果你知道它是一个派生指针并且你想获得一个基指针,你可以这样做:

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

您会发现 Base* 指向与 Derived* 不同的位置,因此需要中间强制转换。


-2
投票

使用

dynamic_cast
,它可以动态告诉你指针是否指向
Base
对象。

© www.soinside.com 2019 - 2024. All rights reserved.