将 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_cast
和static_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* 转换为动态类型的主要内容,如果未能解决你的问题,请参考以下文章
如何“动态”将 Object 类型的实例转换为其特定的数据类型?