Das Casting von Zeigern auf void*
hat seine Bedeutung seit C Tagen. Der am besten geeignete Ort befindet sich im Speichermanager des Betriebssystems. Es muss den gesamten Zeiger und das Objekt von dem, was Sie erstellen, speichern. Indem sie es in void * speichern, verallgemeinern sie es, um jedes Objekt in der Speichermanager-Datenstruktur zu speichern, das heap/B+Tree
einfach sein könnte arraylist
.
Nehmen Sie der Einfachheit halber ein Beispiel für das Erstellen eines list
generischen Elements (Liste enthält Elemente völlig unterschiedlicher Klassen). Das wäre nur mit möglich void*
.
Standard besagt, dass dynamic_cast für illegales Typ-Casting null zurückgeben sollte, und Standard garantiert auch, dass jeder Zeiger in der Lage sein sollte, cast in void * und zurück zu schreiben, mit Ausnahme von Funktionszeigern.
Die normale praktische Verwendung auf Anwendungsebene ist für void*
Typografie sehr gering, wird jedoch häufig in Systemen mit niedriger Ebene / eingebetteten Systemen verwendet.
Normalerweise möchten Sie reinterpret_cast für Low-Level-Inhalte verwenden, wie in 8086, um Zeiger derselben Basis zu versetzen, um die Adresse zu erhalten, ohne darauf beschränkt zu sein.
Bearbeiten:
Standard sagt, dass Sie jeden Zeiger in void*
sogar mit konvertieren können, dynamic_cast<>
aber es gibt nicht an, wo Sie angeben, dass Sie das void*
Zurück nicht in das Objekt konvertieren können .
Für die meisten Zwecke ist es eine Einbahnstraße, aber es gibt einige unvermeidbare Nutzungsmöglichkeiten.
Es heißt nur, dass dynamic_cast<>
Typinformationen benötigt werden, um sie wieder in den angeforderten Typ zu konvertieren.
Es gibt viele APIs, bei denen Sie void*
an ein Objekt übergeben müssen, z. Java / Jni-Code übergibt das Objekt als void*
.
Ohne Typinfo können Sie das Casting nicht durchführen. Wenn Sie sicher genug sind, dass der angeforderte Typ korrekt ist , können Sie den Compiler bitten, dies dynmaic_cast<>
mit einem Trick zu tun .
Schauen Sie sich diesen Code an:
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();
} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}
system("pause");
return 0;
}
Bitte korrigieren Sie mich, wenn dies in keiner Weise korrekt ist.