将void * user_data转换为object

时间:2010-09-22 05:24:28

标签: c++ casting callback

如何将void *something转换为标准C ++中的对象? 具体来说,我想要投射void *userdatastd::map<String, void*>

这可能吗?我在尝试:

//void *user_data is a parameter of this function (callback)
std::map <String, void*> user_data_n; //this line is ok
user_data_n = static_cast<std::map<String, void *>>(*user_data); //I get the errors here.

错误:

Spurious '>>' user '>' to terminate a template argument list
Expected '>' before '(' token
'void *' is not a pointer-to-object type

或者是否有更好的方法来传递有关调用者对象的信息以及我可以传递给void *user_data的其他一些参数?

更新

@aaa carp建议的屁股我将>>更改为> >并解决了前两个错误。最后一个是奇怪的,为什么我在这里投射时会得到那种消息而不是在设置回调时放置那个对象?

std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h; //h was defined as int *h
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);

其中createTrackbar定义为:

int createTrackbar( const string& trackbarname, const string& winname,
int* value, int count, TrackbarCallback onChange, void* userdata);

UPDATE2:

这样做解决了我的问题,但是按照相同的方法,为什么我在尝试转换地图对象中包含的对象时仍然会出错?

void trackbar_handler(int value, void *user_data){
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data); //WORKED!! ;)

MainController *controller; //the same class type I put using "this" above
controller = reinterpret_cast<MainController *>( user_data_map["Object"]); //ERROR here

int *var = reinterpret_cast<int*> (user_data_map["h"]); //ERROR also here

4 个答案:

答案 0 :(得分:6)

>>应为> > 并且您不希望取消引用void指针,而是将void指针转换为所需的指针类型,然后取消引用

@casa已经为您提供了第二个问题的答案

答案 1 :(得分:1)

当您从void *进行投射时,您的结果也将成为指针。所以地图声明应该是:

std::map <String, void*> *user_data_n;

其次,您应该使用reinterpret_cast进行此类(潜在危险)演员:

user_data_n = reinterpret_cast<std::map<String, void *> *>(user_data);

<强>更新

正如其他人所建议的那样,您也可以简单地使用static_cast

  

为什么我在这里投射时会收到这种信息,而不是在设置回调时放置该对象?

任何指针都可以隐式转换为void *,但在将其转换回某个特定类型的指针时,需要显式转换。

  

为什么我在尝试转换地图对象中包含的对象时仍然会出错?

正如评论中已经提到的,您需要在使用地图对象之前取消引用指针。您可能希望定义引用,以简化操作:

std::map <String, void*> &user_data_map =
    *(static_cast<std::map<String, void *> *>(user_data));

答案 2 :(得分:1)

注意到,&gt;&gt;在该行中关闭您的模板应该是&gt; &GT; (有空格)。

此外,如果user_data是void指针,则无法取消引用它。您可以使用reinterpret_cast:

将指针转换为另一种指针类型
std::map <String, void*> *user_data_n_ptr; //note this is a pointer to a map.
user_data_n_ptr = reinterpret_cast<std::map<String, void *> *>(user_data);

这会将void指针强制转换为std :: map。

你应该小心这一点。通常不应该在c ++中抛出void指针。可能有更好的方法来做你想做的事情,并避免一起做空*。

答案 3 :(得分:1)

我想这是为了提供C回调?拥有一个专门的struct可能会更好,它使用确切的类型保留所有这些值。那样你就可以完成一件事。像这样:

struct callback_user_data {
  my_class* that;
  int number;
  callback_user_data(my_class* p, int i) : that(p), number(i) {}
};

// the callback
void my_callback(void* user_data)
{
  callback_user_data* cbud = static_cast<callback_user_data*>(user_data);
  somehow_use(cbud->that, cbud->number);
}

//call the function, passing our user data
callback_user_data cbud(this, 42);
some_function_taking_our_callback(&my_callback, &cbud);

请注意,我通常会看到(并使用过)这个,这样就不会传递特殊类型,而只会传递this,它仍然拥有所有必要的数据:

// the callback
void my_callback(void* user_data)
{
  my_class* that = static_cast<my_class*>(user_data);
  that->f();
  std::cout << that->number << '\n';
}

//call the function, passing our user data
some_function_taking_our_callback(&my_callback, this);