【问题标题】:Convert void* to a dynamic type将 void* 转换为动态类型
【发布时间】: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,你能提供样品吗?谢谢
  • 你可以到处投。编译器将编译。大量未定义的行为,但编译器将关闭并编译比 (myType*) 更迟,这毫无意义。
  • 一个变量不包含它所包含的类型的信息(在运行时)。你不能仅仅尝试使用typeid 并期望它能够工作(而且它是一个 GNU 插件并且会产生额外的开销)

标签: c++ casting void-pointers


【解决方案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() 等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2017-10-07
      • 1970-01-01
      • 2012-01-17
      相关资源
      最近更新 更多