C ++ приведение к void * и восстановление базы - PullRequest
2 голосов
/ 11 января 2012

У меня есть:

class A {...};

class B : public A {...};

class C : public B {...};

Тогда я сохраняю экземпляр C как недействительный *:

C *instance = new C();
void *pC = instance;

Можно ли это сделать:

B *pB = reinterpret_cast<B*>(pC);

Или я должен приводить только к C *?

PS: У меня есть больше классов, полученных из B в моей программе, и я не уверен, что все в порядке, как я делаю (в B *).

Почему void *: Я использую void *userdata' field класса физического тела в движке box2d.Я не могу хранить там свой класс другим способом

Ответы [ 5 ]

3 голосов
/ 11 января 2012

Я бы предложил привести его обратно к исходному C*, затем выполнить dynamic_cast до B*, чтобы следовать правилам C ++ - хотя вам следует избегать приведения к void* в первую очередь и вместо этого использовать базовый указатель (A*) вместо void ptr.

1 голос
/ 11 января 2012

Общее правило заключается в том, что при приведении от указателя к void * вы всегда должны возвращаться к тому, с которого изначально пришли.

Приведение к пустоте * иногда является необходимым злом из-за старых API,

И иногда это делается специально для создания «легкого» шаблона.Легкий шаблон - это место, где вы пишете код, который обрабатывает набор указателей на объекты, которые обрабатываются одинаково, и это предотвращает необходимость генерирования кода для каждого типа.

Вокруг этого кода у вас есть строго типизированный шаблон, который выполняет простую операцию приведения вперед и назад (вероятно, в любом случае встроенную), так что пользователи получают строго типизированный код, но реализация менее раздутая.

1 голос
/ 11 января 2012

Для кода, который вы показали, все в порядке, просто приведите к B*, и вы можете использовать static_cast для этого. Однако в общем случае указатели на базовые и производные классы могут различаться, и вам придется сначала приводить к исходному типу, а только затем приводить его к указателю на базу.

Редактировать: это должно быть хорошо на практике для одиночного наследования, но в целом это UB.

0 голосов
/ 11 января 2012

Бросок в void * - это всегда плохая идея, как и в dynamic_cast. Если вам нужно, это в основном означает, что ваш код требует ре-факторинга, поскольку это недостаток проектирования объекта.

0 голосов
/ 11 января 2012

Это будет хорошо работать.В этом случае вы получите доступ только к методам A и B.(Вы просто «спрячете» методы C.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...