将void *转换为动态类型

时间:2014-09-09 13:52:22

标签: c++ casting void-pointers

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

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

当我想将空指针转换回我使用的双倍时:

 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? 

有可能吗?

3 个答案:

答案 0 :(得分:2)

C / C ++不能很好地交换数据类型,例如JavaScript变量 int值的格式将不同于二进制

中的双值格式(浮点)

在将其转换为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);
}                   

答案 1 :(得分:2)

而不是

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)]
}

答案 2 :(得分:0)

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

如果使用字符串表示类型,则需要从字符串到实际类型的某种映射。虽然你可以从一个字符串到另一个字符串,但是没有转换回来。

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