#c #casting
#c #Кастинг
Вопрос:
У меня возникли проблемы с приведением.
Класс A имеет открытый метод: char* m()
funcA получает двойной указатель на тип A и преобразует его в указатель void. В funcB я хочу привести его обратно к типу A, чтобы я мог вызвать метод m (). Я пробовал нижеприведенное, но с треском провалился.
void funcA(const A** a) {
funcB((void*)a)
}
void funcB(void* b) {
A* a = (A*) b; //
printf("M: %s", a->m()); // => crash!
}
Как я могу преобразовать указатель void обратно в тип A, чтобы я мог вызвать метод?
Комментарии:
1. Ну,
A*
иA**
это две разные вещи.2.
const **A a
Действительно ли допустимый синтаксис? Разве это не должно бытьconst A ** a
?3. @rattmuff: Как бы вы вызвали метод из
funcA
?4. @unwind Так и должно быть, ошибка публикации.
5. @pts Я не понимаю, это вызывается из системы, находящейся вне моего контроля. Я управляю только funcB.
Ответ №1:
Две возможности:
void funcA(const A** a) {
funcB((void*)*a); // passing an A* to funcB
}
void funcB(void* b) {
A* a = (A*) b;
[...]
}
или
void funcA(const A** a) {
funcB((void*)a); // passing an A** to funcB
}
void funcB(void* b) {
A* a = *(A**)(b);
[...]
}
Обратите внимание, что тип, который мы используем для приведения b
в funcB
, должен соответствовать типу того, что мы передали из funcA
. Это легко ошибиться, поскольку мы удаляем всю информацию о типе после приведения к void*
, поэтому компилятор не может нам здесь помочь.
Также имейте в виду, что при том, как это написано сейчас, мы теряем const
квалификатор в оригинале a
. Это потенциально плохо. Возможно, вместо этого вы захотите привести к const A*
in funcB
.
Ответ №2:
Type**
является указателем на Type*
, в то время как Type*
является указателем на объект типа Type
.
Итак, если мы предположим, что funcA
получает действительный указатель на указатель на объект типа A
, вы должны сначала разыменовать его с помощью *
оператора.
funcB((void*) *a)
Вы должны видеть A** a
параметр таким, какой он есть на самом деле — значением в памяти. Это значение является адресом, точнее адресом a A*
. Итак, если вы разыменовываете a A**
, вы получаете A*
. Полученное значение снова является адресом, но самого объекта типа A
.
A**
содержит адрес кA*
A*
содержит адрес объекта типаA
Ответ №3:
Проблема в том, что параметр a
в funcA
является A**
, не A*
. Таким образом, вы начинаете с A**
и заканчиваете на A*
, и адреса не имеют членов.