代码之家  ›  专栏  ›  技术社区  ›  nacho4d

将void*用户数据强制转换为对象

  •  3
  • nacho4d  · 技术社区  · 14 年前

    我怎么铸 void *something 标准C++中的对象? 我特别想演 void *userdata std::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鲤鱼建议的驴我换了 >> > > 前两个错误都解决了。最后一个很奇怪,为什么在这里强制转换时会收到这种消息,而在设置回调时不在放置对象时收到这种消息?

    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);
    

    更新2:

    这样做解决了我的问题,但遵循同样的方法,为什么我在尝试投射包含在我的地图对象中的对象时仍然会出错?

    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 回复  |  直到 14 年前
        1
  •  1
  •   casablanca    14 年前

    当你从一个 void * ,您的结果也将是一个指针。所以地图声明应该是:

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

    第二,你应该使用 reinterpret_cast 对于此类(潜在危险)铸件:

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

    更新:

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

    为什么在这里强制转换时会收到这样的消息,而在设置回调时不在放置对象时收到?

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

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

    正如注释中已经提到的,在使用映射对象之前需要取消对指针的引用。您可能希望定义一个引用,而不是使事情更简单:

    std::map <String, void*> &user_data_map =
        *(static_cast<std::map<String, void *> *>(user_data));
    
        2
  •  6
  •   Andreas Magnusson    14 年前

    >> 应该是 > > 您不希望取消对void指针的引用,而是将void指针强制转换为所需的指针类型,然后取消对void指针的引用。

    @CASA已经向您提供了第二个问题的答案

        3
  •  1
  •   JoshD    14 年前

    注意,该行中关闭模板的行应为(带空格)。

    此外,如果用户数据是空指针,则不能取消对它的引用。您可以使用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);
    

    这将将空指针转换为STD::MAP。

    你应该小心点。在C++中通常不应该抛出空指针。也许有更好的方法来做你想做的事情,同时避免空虚。

        4
  •  1
  •   sbi    14 年前

    我想这是为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);