Frage

Bin ich recht in der Annahme, dass C-Casts (die entmutigt sind) sind nichts anderes als reinterpret_casts? letzteres unter Verwendung von optisch fällt und einfach, wenn für böse Abgüsse und daher wird empfohlen, über C-Casts?

suchen zu suchen

Wenn Wegwerfen const const_cast verwenden und auf ein ursprünglich konstantes Objekt zu schreiben ist nicht definiert, was ist der Zweck der const_cast?

Hinweis: Ich weiß, dass Bjarne verurteilt zu Recht Gießvorgängen, dass sie unsicher sind und geht sogar soweit, der besagt, „Ein hässlich Operation sollte eine hässliche syntaktische Form hat. " und damit die Ausführlichkeit der Operatoren in C ++ Gießen. Also werde ich versuchen, ihre Nutzung zu minimieren. Versprechen. :)

War es hilfreich?

Lösung

Nein. A C Guss kann die äquivalent einen const_cast tun, ein static_cast, ein reinterpret_cast oder eine Kombination davon. Im Fall, dass nicht genug war, kann es auch mindestens einen Moll-Trick, dass nicht Kombination des neueren Abgüsse überhaupt tun kann!

Sie können const_cast mit definierten Ergebnis zu erzielen, wenn die ursprüngliche Variable ohne const definiert ist, aber alles, was Sie haben, ist ein const Zeiger oder eine Referenz auf das Objekt. OTOH, wenn Sie denken, Sie haben einen guten Grund eine const_cast zu verwenden, stehen die Chancen, dass Sie wirklich statt mutable aussehen sollte.

Edit: Ich glaube, ich sollte es weg vom Recht gesagt haben, aber ein C-Casts kann zu einer unzugänglichen Basisklasse konvertieren. Betrachten wir zum Beispiel so etwas wie:

[Edit: Ich bin Aktualisierung des Code auf etwas, das kompilieren werden und (in der Regel) demonstriert Problem. ]

#include <iostream>

class base1 {
public:
    virtual void print() { std::cout << "base 1\n"; }
};

class base2 {
public:
   virtual void print() { std::cout << "base 2\n"; }
};

class derived : base1, base2 {}; // note: private inheritance

int main() {    
    derived *d = new derived;
    base1 *b1 = (base1 *)d;    // allowed
    b1->print();    // prints "base 1"
    base2 *b2 = (base2 *)d;    // also allowed
    b2->print();    // prints "base 2"

//    base1 *bb1 = static_cast<base *>(d);  // not allowed: base is inaccessible

    // Using `reinterpret_cast` allows the code to compile.
    // Unfortunately the result is different, and normally won't work. 
    base1 *bb2 = reinterpret_cast<base1 *>(d);
    bb2->print();   // may cause nasal demons.

    base2 *bb3 = reinterpret_cast<base2 *>(d); 
    bb3->print();   // likewise
    return 0;
}

Der Code der reinterpret_casts mit kompiliert - aber versuchen, das Ergebnis zu verwenden (zumin damit einer der beiden) wird ein großes Problem verursachen. Die reinterpret_cast nimmt die Basis Adresse des abgeleiteten Objekts und versucht, sie zu behandeln, als ob es die angegebene Art von Basisobjekt war - und da (höchstens) ein Basisobjekt kann an dieser Adresse tatsächlich existiert, versuchen, es wie die andere Dose zu behandeln / wird zu großen Problemen führen. Edit: In diesem Fall sind die Klassen im Wesentlichen identisch mit der Ausnahme, was sie drucken, so dass, obwohl alles könnte passieren, mit den meisten Compilern, die beide der letzten beiden druckt out „Basis 1“. Die reinterpret_cast nimmt, was an dieser Adresse und versucht zu sein geschieht es mit dem angegebenen Typ zu verwenden. In diesem Fall habe ich (versucht) machen, die etwas harmlos tun, aber sichtbar. In echtem Code, wird das Ergebnis wahrscheinlich nicht so schön sein.

Der C-Casts wird wie ein static_cast arbeiten würde, wenn der Code öffentliche Vererbung benutzt hatte, statt privat - das heißt, es ist bekannt, wo in der abgeleiteten Klasse jede Basisklasse Objekt „lebt“, und stellt das Ergebnis, so dass jeder resultierende Zeiger funktionieren werden, weil es an der richtigen Stelle.

Punkt eingestellt ist schon

Andere Tipps

Nein, C-Casts können als reinterpret_casts, const-casts oder static_casts wirken auf die Situation abhängig. Aus diesem Grund ist sie entmutigt sind - Sie einen C-Casts in Code und müssen schauen Details siehe, um zu sehen, was es tun wird. Zum Beispiel:

const char* source;
int* target = (int*)source;// - acts as const_cast and reinterpret_cast at once
//int* target = retinterpret_cast<int*>source;// - won't compile - can't remove const

Denken Sie daran, dass eine konstante Besetzung auf etwas anderes handeln kann dann die ursprüngliche Kennung:

void doit(const std::string &cs)
{
    std::string &ms = const_cast<std::string &>(cs);
}

int main()
{
    std::string s;
    doit(s);
}

Während also doit wirft weg const, in diesem Beispiel die zugrunde liegenden Zeichenfolge ist nicht const so kein undefiniertes Verhalten.

Aktualisieren

Okay, hier ist ein besseres Beispiel, wenn const_cast verwendet, ist nicht völlig wertlos. Wir beginnen mit einer Basisklasse mit einer virtuellen Funktion, die einen const Parameter annimmt:

class base
{
public:
    virtual void doit(const std::string &str);
};

und jetzt wollen Sie diese virtuelle Funktion außer Kraft zu setzen.

class child : public base
{
public:
    virtual void doit(const std::string &str)
    {
        std::string &mstr = const_cast<std::string &>(str);
    }
};

Aufgrund der Logik / Struktur des Codes, wissen Sie, dass child::doit nur mit nicht konstanten Strings aufgerufen werden (und class base ist unter Ihrer Kontrolle nicht, so dass Sie es nicht ändern können, noch können Sie die Unterschrift von child::doit ändern, weil dann wird es nicht mehr überschreiben base::doit). In diesem Fall ist es sicher konst wegzuwerfen.

Ja, das ist riskant. Vielleicht, wenn Sie schreiben, dass, es ist wahr, dass die Ausführung nie child::doit mit einem nicht-const string erreichen und der Code gültig ist. Aber das könnte entweder ändern, während Ihr Programm beibehalten oder vielleicht, wenn Sie wieder aufzubauen und die neueste Version von class base abholen.

const_cast verwendet const von einem Typ zu entfernen. Es kann auch volatile entfernen. Wenn das Objekt wirklich const wird, dann kann das Ergebnis nicht zu und noch Verhalten gut definiert werden, geschrieben werden. Wenn jedoch wird es zu const gefördert (indem sie in eine const T Funktion übergeben wird, dann ist es const_casting zurück zu nicht-const ist in Ordnung. (I ein paar mehr Infos gefunden hier )

reinterpret_cast kann nicht Entfernen const oder volatile von einem Typ.

auch

C-Casts sind wirklich der Hammer Schlitten der Programmierung - Sie grundsätzlich den Compiler sagen, dass die quadratischen Pflock dort durch dieses runde Loch passt, egal was. In diesem Sinne ist reinterpret_cast sehr ähnlich.

Der Hauptvorteil ich bei der Verwendung der C ++ sehen - Casts Operatoren sind, dass sie ermöglichen es Ihnen, Ihre Absicht besser auszudrücken und dem Compiler noch über den Betrieb bis zu einem gewissen Kontrolle ermöglicht es Ihnen, es sind gefragt ein- bis ausführen, anstatt size-fits-all-Stil C gegossen.

In Bezug auf const_cast- Sie oft in die Situation kommen, wo Sie ein Objekt um über konstante Referenz einfach sind vorbei, da die API Sie erfordert dies zu tun. Sag mal, du hast Funktion X bekam, dass die Aufgaben einer C-String:

void X(const char *str) { ... }

Im Inneren, die Sie funktionieren vorbei sind die Parameter an eine C-Funktion, die eine char * erwartet, auch wenn die Zeichenfolge nicht ändert sich. Der einzige Weg, dies zu unterbringen zu const_cast str sein würde.

würde ich sehr vorsichtig sein, jede Art von Besetzung mit, oft dies zeigt, dass es etwas nicht ganz richtig mit Ihrem Design ist aber manchmal muss man die Compiler davon überzeugen, dass der Stift an es sieht nicht so quadratisch wie es annimmt, . Erst dann sollten Sie die Cast-Operatoren verwenden.

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