2016-11-10 4 views
0

Warum kann der folgende Code nicht kompilieren?const_cast zu "void pointer" von "const T pointer" schlägt fehl

CFDictionaryRef dictionary; 

CFDictionaryApplyFunction (dict, Set, const_cast < void *> (Wörterbuch));

error: const_cast from 'CFDictionaryRef' (aka 'const __CFDictionary *') to 'void *' is not allowed 
    CFDictionaryApplyFunction(scoped, setDictionary, const_cast<void *>(dictionary)); 
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Wenn ich gesetzt c-style type Guss void * es funktioniert gut

CFDictionaryApplyFunction (dict, Set, (void *) Wörterbuch);

+5

Weil 'const_cast' nur die' const'ness eines Typs *** umwandelt. Wenn Sie zwischen einem "const" -Zeiger eines Typs und einem veränderbaren Zeiger eines anderen Typs umwandeln möchten, müssen Sie zuerst die 'const'-Ness mit' const_cast' und anschließend 'reininterpret_cast' mit dem Befehl" cast "umsetzen . Die Tatsache, dass zwei Abgüsse notwendig sind, ist eine hupende rote Flagge, dass etwas grundsätzlich mit dem Code, der dies tun muss, überhaupt nicht stimmt. Richtig entworfener und geschriebener Code muss das nie tun. Was immer dein wirkliches Problem ist, ist es nicht. –

+1

Ein 'const_cast' und' static_cast' würden tun. – aschepler

+0

Was sind die Argumenttypen für die CFDictionaryApplyFunction-Methode? – Garland

Antwort

1

Do reinterpret_cast<void *>(const_cast< __CFDictionary * >(dictionary))

const_cast nur zwischen const Zeiger oder Verweise und ihre nicht const Äquivalente zu werfen entworfen. Um in einen anderen Typ zu konvertieren (void* in Ihrem Fall), müssen Sie reinterpret_cast verwenden. reinterpret_cast "reinterpretiert" grundsätzlich die gleiche Bitfolge wie ein anderer Typ. Es ist jedoch nicht erlaubt, Konstanz wegzuwerfen, also müssen beide Formen zusammen verwendet werden.

EDIT: Da @AnT darauf hinweist, da das Ziel void * ist, können Sie static_cast statt reinterpret_cast verwenden. In der Tat wird es als sicherer angesehen, da der Standard garantiert, dass Sie als Ergebnis die gleiche Adresse erhalten. reinterpret_cast hingegen garantiert nur, dass der ursprüngliche Wert durch das Ergebnis des ersten Rückschritts erhalten wird. Dies gilt jedoch nur für einen eingeschränkten Satz von Konvertierungen (void *, Basis-abgeleitete Klassenpaare). reinterpret_cast ist allgemeiner, obwohl Sie auf den Compiler angewiesen sind, um das Vernünftige zu tun.

+1

Während dieses Code-Snippet die Frage lösen kann, einschließlich einer Erklärung [wirklich hilft] (// meta.stackexchange.com/q/114762), um die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in der Zukunft beantworten, nicht nur die Person, die jetzt fragt! Bitte [bearbeiten] Sie Ihre Antwort, um eine Erläuterung hinzuzufügen und geben Sie an, welche Einschränkungen und Annahmen gelten. –

+0

Erstens, es ist nicht nötig, 'reininterpret_cast' für das Casting in' void * 'einzubeziehen. 'static_cast' kann das tun. Hier ist keine "Neuinterpretation" nötig. Zweitens bezieht sich "neu interpretieren" in "reinterpret_cast" nicht auf das Neuinterpretieren von Bits des konvertierten Werts. Er bezieht sich auf die Neuinterpretation des Werts, auf den der Zeiger zeigt (oder der durch Referenz referenziert wird). Da in diesem Fall einer der Typen "void *" ist, gibt es wirklich keine sinnvolle "Neuinterpretation", da "void" -Objekte nicht existieren. – AnT

+0

Korrigieren Sie mich, wenn ich falsch liege, aber ich bezog mich auf dieses: http://en.cppreference.com/w/cpp/language/reinterpret_cast – SPMP