Приведение указателей к void*
имеет значение еще с C дней.
Наиболее подходящее место находится внутри менеджера памяти операционной системы. Он должен хранить весь указатель и объект того, что вы создаете. Сохраняя его в void *, он обобщает его для сохранения любого объекта в структуре данных диспетчера памяти, который может быть heap/B+Tree
или простым arraylist
.
Для простоты возьмем пример создания list
общих элементов (список содержит элементы совершенно разных классов). Это было бы возможно только при использовании void*
.
стандарт говорит, что dynamic_cast должен возвращать ноль для недопустимого приведения типов, а стандарт также гарантирует, что любой указатель должен иметь возможность типизировать приведение его к void * и обратно из него, за исключением только указателей на функции.
Обычное практическое применение на уровне приложений очень мало для void*
приведения типов, но оно широко используется в низкоуровневых / встроенных системах.
Обычно вы хотите использовать reinterpret_cast для вещей низкого уровня, как в 8086 году он используется для смещения указателя той же базы, чтобы получить адрес, но не ограничивается этим.
Edit:
Стандарт говорит, что вы можете конвертировать любой указатель в void*
даже с dynamic_cast<>
, но это не означает, что вы не можете конвертировать void*
обратно в объект.
В большинстве случаев это улица с односторонним движением, но есть неизбежное использование.
Он просто говорит, что dynamic_cast<>
нужна информация о типе для преобразования его обратно в запрошенный тип.
Существует много API, которые требуют, чтобы вы передавали void*
какому-либо объекту, например. java / jni код передает объект как void*
.
Без информации о типе вы не можете выполнять приведение. Если вы достаточно уверены, что запрошенный тип является правильным , вы можете попросить компилятор сделать dynmaic_cast<>
с помощью хитрости.
Посмотрите на этот код:
class Base_Class {public : virtual void dummy() { cout<<"Base\n";} };
class Derived_Class: public Base_Class { int a; public: void dummy() { cout<<"Derived\n";} };
class MostDerivedObject : public Derived_Class {int b; public: void dummy() { cout<<"Most\n";} };
class AnotherMostDerivedObject : public Derived_Class {int c; public: void dummy() { cout<<"AnotherMost\n";} };
int main () {
try {
Base_Class * ptr_a = new Derived_Class;
Base_Class * ptr_b = new MostDerivedObject;
Derived_Class * ptr_c,*ptr_d;
ptr_c = dynamic_cast< Derived_Class *>(ptr_a);
ptr_d = dynamic_cast< Derived_Class *>(ptr_b);
void* testDerived = dynamic_cast<void*>(ptr_c);
void* testMost = dynamic_cast<void*>(ptr_d);
Base_Class* tptrDerived = dynamic_cast<Derived_Class*>(static_cast<Base_Class*>(testDerived));
tptrDerived->dummy();
Base_Class* tptrMost = dynamic_cast<Derived_Class*>(static_cast<Base_Class*>(testMost));
tptrMost->dummy();
//tptrMost = dynamic_cast<AnotherMostDerivedObject*>(static_cast<Base_Class*>(testMost));
//tptrMost->dummy(); //fails
} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}
system("pause");
return 0;
}
Пожалуйста, поправьте меня, если это не так.