2010-09-22 3 views
3

как мне сделать void *something объекту в стандартном C++? В частности, я хочу хочу бросить void *userdata в std::map<String, void*>Кастинг void * user_data для объекта

Возможно ли это? Я пытаюсь:

//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?

UPDATE:

Ass предложил @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); 

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 
+0

Есть ли конкретная причина, по которой 'user_data' должен быть' void * '? – Paul

+0

yes, потому что это функция из библиотеки OpenCV и void * предназначена для передачи любых данных, которые будут использоваться в функции обратного вызова. – nacho4d

+0

'map [foo]' возвращает ключ/значение std :: пара – Anycorn

ответ

1

Когда вы кастинг от void *, ваш результат будет указателем тоже. Таким образом, декларация карта должна быть:

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

Во-вторых, вы должны использовать reinterpret_cast для таких (потенциально опасных) бросает:

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

Update:

Как и другие предложили, вы могли бы просто используйте также static_cast.

Почему я получаю такое сообщение при его использовании здесь, а не при помещении этого объекта при настройке обратного вызова?

Любой указатель может быть неявно преобразован в void *, но при преобразовании его обратно в указатель некоторого определенного типа, вам нужно явное приведение.

Почему я все еще получаю ошибку при попытке наложения объектов, содержащихся в моем объекте карты?

Как уже упоминалось в комментариях, перед использованием объекта карты необходимо разыменовать указатель. Вы можете определить ссылку вместо того, чтобы сделать вещи проще:

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

Я думаю, что это нормально использовать статический бросок, если вы знаете, что указатель void был фактически типом – Anycorn

+2

Я не буду -1, но вы должны 'static_cast'. Это абсолютно безопасно для 'static_cast', если вы вернетесь к тому же типу, и ничего не получите, используя' reinterpret_cast'. – GManNickG

+0

Я обновил свой вопрос, пожалуйста, взгляните. спасибо – nacho4d

6

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

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

+0

, который решил первые 2 ошибки! ;) Одна ошибка слева; ( – nacho4d

+0

@nac см. Обновление – Anycorn

+0

В стандарте указано: «Указатель на объект может быть явно преобразован в указатель на объект другого типа.65) За исключением того, что преобразование rvalue типа« указатель на T1 » к типу «указатель на T2» (где T1 и T2 являются типами объектов и где требования к выравниванию T2 не являются более строгими, чем требования T1) и обратно к исходному типу дают исходное значение указателя, результат такого преобразования указателя не указано ». – Chubsdad

1

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

Кроме того, если 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); 

Это будет отбрасывать указатель недействительным к станд :: карте.

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

+1

Я использовал один сегодня, пришлось принять душ потом. :-( – Anycorn

+0

Я обновил свой вопрос, пожалуйста, посмотрите. – nacho4d

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); 
Смежные вопросы