Frage

Ich brauche einen integralen Typ zu konvertieren, die eine Adresse auf den tatsächlichen Zeigertyp enthält. Ich konnte verwenden reinterpret_cast wie folgt:

MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);

Dies ist jedoch führt keine Laufzeit überprüft, ob die betreffende Adresse tatsächlich ein MyClass Objekt enthält. Ich möchte wissen, ob es einen Nutzen ist in erster zu einer void * Umwandlung (mit reinterpret_cast) und dann auf das Ergebnis mit dynamic_cast. Wie folgt aus:

void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);

Gibt es einen Vorteil in der zweiten Methode?

War es hilfreich?

Lösung

Geben Sie auf dynamic_cast Überprüfung auf unterschiedliche Weise durch verschiedene C ++ Implementierungen umgesetzt wird; wenn Sie eine Antwort für Ihre spezifische Implementierung möchten, sollten Sie erwähnen, welche Implementierung Sie verwenden. Der einzige Weg, die Frage im allgemeinen zu beantworten ist der ISO-Norm C ++ zu verweisen.

Durch meine Lektüre der Norm, ruft dynamic_cast auf einem void-Zeiger ist illegal:

dynamic_cast<T>(v)
  

„Wenn T ein Zeigertyp ist, v ist ein R-Wert eines Zeigers sein Klassentyp zu vervollständigen“

(von 5.2.7.2 der Norm ISO ++ C). void ist kein vollständiger Klasse-Typ, so der Ausdruck ist illegal.

Interessanterweise wird die Art werfen darf einen void-Zeiger sein, d.

void * foo = dynamic_cast<void *>(some_pointer);

In diesem Fall ist die dynamic_cast immer erfolgreich ist, und der sich ergebende Wert ist ein Zeiger auf den meisten abgeleitetes Objekt, auf das durch v.

Andere Tipps

Nein, es gibt keinen besonderen Vorteil dabei. In dem Moment, Sie reinterpret_cast verwenden, sind alle Wetten ab. Es liegt an Ihnen, um sicherzustellen, dass die Besetzung gültig ist.

Eigentlich kein ernsthafter Vorteil. Wenn die void * zeigt auf etwas, das nicht ein Zeiger auf ein polymorphes Objekt ist, dass Sie in undefiniertes Verhalten führen (in der Regel einer Zugriffsverletzung) sofort.

Der sichere Weg ist eine Aufzeichnung aller Live-MyClass Objekte zu halten. Es ist am besten, diese Aufzeichnung in einem std::set<void*> zu halten, was bedeutet, dass Sie leicht hinzufügen, entfernen und Testelemente.

Der Grund, sie als void*s zum Speichern ist, dass Sie nicht nastyness riskieren wie unaligned MyClass* Zeiger aus dem ganzen Zahl zu schaffen.

  • Zunächst einmal „neu zu interpretieren“ int zu void * ist eine schlechte Idee. Wenn sizeof(int) 4 und sizeof(void *) ist 8 (64x-System) ist schlecht ausgebildet sind.

  • Darüber hinaus dynamic_cast gilt nur für den Fall der polymorphen Klassen.

Option 1 ist die einzige (halb) portable / gültige Option.

Option 2: ist nicht gültig C ++ als dynamic_cast (void ist nicht erlaubt)

.

Bei einer Implementierungsebene erfordert es Informationen aus dem Quelltyp eingeben, um den Zieltyp zu erhalten. Es gibt keine Möglichkeit (oder es kann keine Möglichkeit gegeben sein), um die Laufzeitquelle Typinformationen aus einer Lücke zu bekommen * so ist dies entweder nicht gültig.

dynamic_cast wird verwendet, um cas auf und ab der Typenhierarchie nicht von unbekannten Typen.

Als Seite beachten sollen Sie wahrscheinlich ungültig mit * anstatt einer ganzen Zahl mit einem nicht typisierten Zeiger zu speichern. Es gibt Potenzial für ein int nicht groß genug sein, um einen Zeiger zu speichern.

Der sicherste Weg, Zeiger in C ++ zu handhaben ist, sie typsicher zu handhaben. Das bedeutet:

  • Nie speichern Zeiger in etwas anderes als ein Zeiger
  • Vermeiden void-Zeiger
  • Sie niemals passieren Verweise auf andere Prozesse
  • betrachten weak_ptr wenn Sie Zeiger über Threads verwenden

Der Grund dafür ist: was Sie planen, unsicher zu tun ist, und kann vermieden werden, es sei denn, Sie (legacy?) Code unsicher mit Schnittstellen sind. In diesem Fall betrachtet MSalters' Antwort, aber bewusst sein, dass es immer noch ein Streit ist.

Wenn Sie sicher wissen, dass the_integer Punkte auf einen bekannten Basisklasse (dh mindestens ein virtuelles Mitglied), da in der Tat könnte ein Vorteil sein: zu wissen, dass das Objekt einer bestimmten Klasse abgeleitet ist. Aber man müßte zuerst an Ihre Basisklasse reinterpret_cast und dann die dynamic_cast tun:

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);

ein void* in dynamic_cast Verwendung ist nutzlos und einfach falsch. Sie können nicht dynamic_cast verwenden um zu überprüfen, ob es an einer beliebigen Stelle im Speicher ein gültiges Objekt ist.

Sie sollten auch darauf achten, wenn Adressen in Nicht-Zeiger-Typ-Variablen zu speichern. Es gibt Architekturen, bei denen sizeof (void *)! = Sizeof (int), z.B. LP64.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top