将 void* 转换为动态类型

Posted

技术标签:

【中文标题】将 void* 转换为动态类型【英文标题】:Convert void* to a dynamic type 【发布时间】:2014-09-09 13:52:22 【问题描述】:

我有一个双变量i,它被转换成一个名为pointer的空指针:

 double i = 3; 
 void *pointer = &i;

当我想将 void 指针转换回双精度时,我使用了:

 double p = *((double*) pointer); 

我想将 void 指针转换为我将作为 char* 发送的类型:

 char* myType= typeid(i).name();//get the name of type of "i"
 int p = *((myType*) pointer); // how to implement? 

有可能吗?

【问题讨论】:

您不应该在 C++ 中使用 C 样式转换。首选dynamic_caststatic_cast @RedX,你能提供样品吗?谢谢 What about googling for a tutorial? 你可以到处投。编译器将编译。大量未定义的行为,但编译器将关闭并编译比 (myType*) 更迟,这毫无意义。 一个变量不包含它所包含的类型的信息(在运行时)。你不能仅仅尝试使用typeid 并期望它能够工作(而且它是一个 GNU 插件并且会产生额外的开销) 【参考方案1】:

而不是

char* myType= typeid(i).name();//get the name of type of "i"
int p = *((myType*) pointer); // how to implement? 

使用

typedef decltype(i) myType;
myType p = *((myType*) pointer);

或更好:

typedef decltype(i) myType;
auto p = *reinterpret_cast<myType*>(pointer);

适用于 c++11 或更高版本。如果你想在旧的 c++ 编译器上 decltype,它在 boost 中被模拟。

编辑。这可能与您想要做的不同,我想是这样的:

void myFunction(void* unknownParam) 
    typedef (realTypeOf unknownParam) RealType; // <-- this is not real c++
    RealType &a = *reinterpret_cast<RealType*>(unknownParam)
    //do stuff using 'a'

这在 C++ 中是不可能的,但有一个原因:它没有多大意义。 原因是myFunction 要有效,//do stuff using 'a' 部分应该对RealType 最终成为的任何类型都有效。因此,它不能依赖RealType 类型的任何特性:它不能使用它的任何方法,它不能使用任何运算符,它甚至不知道它是否是一个类。基本上,除了在void* 上已经能够做的事情之外,您不能用它做更多的事情,因此给类型命名并不能真正帮助您。

与您想要的(但不完全是)类似的语言功能是类型反射,它在 C++ 中不存在,但您可以在 Java、Objective-C 或 C# 等语言中找到它。基本上,您询问对象本身是否具有某种方法,并最终调用它。 Objective-C 中的一个例子

-(void)myFunction:(id)unknownParam 
    if([unknownParam respondsToSelector:@selector(myMethod)])
        [unknownParam performSelector:@selector(myMethod)]

【讨论】:

在 C++ 中使用 C 样式转换是不好的做法,因为不清楚您是否正在执行语义转换 (static_cast),将地址重新解释为其他内容 (reinterpret_cast),或删除 const 限定符 (const_cast),因此您可能认为您正在做一个,而实际上编译器正在使用另一个,导致意外行为。 再次感谢。是否可以将 decltype 作为参数发送? 是的。您可以在任何需要使用类型名称的地方使用decltype(expression)(即,声明变量、类成员、参数和函数的返回值、强制转换表达式、模板参数、构造函数调用......) 谢谢。我明白这是可能的。您能否发布一个如何实施的示例?我想向方法发送 void 指针和类型。该方法进行演员表。你能帮帮我吗?【参考方案2】:

C/C++ 不能很好地交换数据类型,例如 javascript 变量 int 值的格式将不同于二进制中的 double 值格式(浮点)

在将 typeid 强制转换为 void* 后,您无法使用 typeid 获取原始数据类型。另请注意,typeid 在不同的操作系统和编译器上会有不同的输出

double dValue = 77.7;
void* pValue = &dValue;

//output "pV" / pointer void (depending on compiler and OS)
std::cout << typeid(dValue).name() << std::endl;

要使用字符串从 void* 转换,您可以制定如下规则。或者您可以尝试在特定情况下使用 C++ 模板函数。

int iOutValue = 0;
double dOutValue = 0;

char* name = "double";
if(!strcmp(name, "int"))

    iOutValue = *((int*)pValue);

else if(!strcmp(name, "double"))

    dOutValue = *((double*)pValue);
                   

【讨论】:

【参考方案3】:

如果您使用某种变体类型而不是传递 void*,则可以将其转换回来。

如果您使用字符串来指示类型,您将需要某种从字符串到实际类型的映射。虽然你可以从类型转到字符串,但没有转换回来。

假设您知道您的基础数据在某种程度上始终是数字的,那么有一些方法可以让特殊的离散变体只包含数字。最简单的方法是存储一个 64 位 int 和一个 double 的并集,以及一些指示您拥有哪一个的标志,然后存储一个转换为任何数字类型的方法,asDouble()asLong() 等。

【讨论】:

以上是关于将 void* 转换为动态类型的主要内容,如果未能解决你的问题,请参考以下文章

DotNet:是不是可能将动态转换为接口类型

在运行时将对象转换为动态类型

如何“动态”将 Object 类型的实例转换为其特定的数据类型?

Golang:将接口动态转换为类型化变量

我正在尝试将 Object 转换为动态类型,但转换失败并出现 RunTimeBinder 异常

动态内存分配函数