Приведение void * user_data к объекту - PullRequest
3 голосов
/ 22 сентября 2010

как мне привести 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 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 ]

6 голосов
/ 22 сентября 2010

>> должно быть > >, и вы не хотите разыменовывать пустой указатель, вместо этого приведите пустой указатель к нужному типу указателя и затем разыменуйте

@ casa уже предоставил вам ответ на вторую проблему

1 голос
/ 22 сентября 2010

Полагаю, это для обслуживания обратного вызова 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);
1 голос
/ 22 сентября 2010

Замечание: >> в этой строке, чтобы закрыть шаблон, должно быть>> (с пробелом).

Кроме того, если user_data является пустым указателем, вы не можете разыменовать его. Вы можете привести указатель к другому типу указателя с помощью 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.

Вы должны быть осторожны с этим. указатели void обычно не должны быть разбросаны в c ++. Может быть, есть лучший способ сделать то, что вы хотите, и избегать пустоты * все вместе.

1 голос
/ 22 сентября 2010

Когда вы кастуете из 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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...