Domanda

Ho ragione nel ritenere che il C stile cast (in cui sono scoraggiati) non sono nulla, ma reinterpret_casts?Con il primo, è di grande impatto visivo e di facile ricerca quando alla ricerca di brutto getta, e quindi è consigliata la C-stile getta?

Se la fusione di distanza const utilizzando const_cast e scrittura originariamente const oggetto è definito, qual è lo scopo di const_cast?

Nota: So che Bjarne giustamente condanna casting operazioni che essi sono sicuri e va fino al punto di affermare "Un brutto l'operazione dovrebbe avere un brutto forma sintattica.", e quindi il livello di dettaglio del casting operatori in C++.Cercherò, quindi, di ridurre al minimo il loro utilizzo.La promessa.:)

È stato utile?

Soluzione

No.A C cast può fare l'equivalente di un const_cast, un static_cast, un reinterpret_cast, o una combinazione di essi.Nel caso In cui non fosse abbastanza, si può anche fare almeno un piccolo trucco che no la combinazione della più recente calchi possono fare tutti!

È possibile utilizzare const_cast con risultati predefiniti se la variabile è definita senza const, ma tu hai un const puntatore o un riferimento a tale oggetto.OTOH, se pensi di avere un buon motivo per utilizzare un const_cast, le probabilità sono che si dovrebbe davvero cercare mutable invece.

Edit:Suppongo che avrei dovuto dire subito, ma un cast di tipo C può convertire in un inaccessibile classe base.Per esempio, prendere in considerazione qualcosa di simile:

[Edit:Sto aggiornando il codice per qualcosa che ti compilazione e (di solito) dimostrare problema.]

#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;
}

Il codice utilizzando il reinterpret_casts compilare -- ma il tentativo di utilizzare il risultato (di almeno uno dei due) sarà causa di un grave problema.Il reinterpret_cast prende il base indirizzo dell'oggetto derivato e cerca di trattarlo come se fosse specificato il tipo di oggetto di base -- e dato che (al massimo) a un oggetto di base può effettivamente esiste a questo indirizzo, cercando di trattare come gli altri possono inoltre causare gravi problemi.Edit:In questo caso, le classi sono essenzialmente identici, tranne che per quello che la stampa, quindi, anche se nulla potrebbe accade con la maggior parte dei compilatori, gli ultimi due stamperà "base 1".Il reinterpret_cast prende tutto ciò che accade all'indirizzo e tenta di utilizzarlo come specificato tipo.In questo caso, io ho (provato) che rendono fare qualcosa di innocuo, ma visibile.Nel codice reale, il risultato probabilmente non sarà così bella.

Il cast di tipo C funzionerà come un static_cast se il codice aveva usato patrimonio pubblico invece di privato-cioèdi essere a conoscenza di in cui la classe derivata ogni oggetto della classe base "vita", e regola il risultato, in modo che ogni conseguente puntatore lavoro perché è stato rettificato il punto al posto giusto.

Altri suggerimenti

No, C-stile calchi possono agire come reinterpret_casts, const-casts o static_casts a seconda della situazione.Questo è il motivo per cui sono scoraggiati - si vede un cast di tipo C in codice e bisogno di guardare per dettagli vedere che cosa farà.Per esempio:

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

Ricordate che un const cast può agire su qualcosa di diverso l'originale identificativo:

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

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

Così, mentre doit è colata via const, in questo esempio la stringa sottostante non è costante, in modo che nessun comportamento indefinito.

Aggiornamento

Bene, ecco un esempio migliore di quando si utilizza const_cast non è completamente inutile.Iniziamo con una classe di base con una funzione virtuale che prende un parametro const:

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

e ora si desidera ignorare la funzione virtuale.

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

A causa della logica/struttura del codice, si sa che child::doit potrà essere chiamato solo con i non-const stringhe (e class base non è sotto il vostro controllo, quindi non è possibile modificare né è possibile modificare la firma child::doit perché allora non si è più ignorare base::doit).In questo caso, è sicuro di cast away const.

Sì, questo è rischioso.Forse, quando si scrive che, è vero che l'esecuzione non potrà mai raggiungere child::doit con un non-const stringa e il codice non è valido.Ma che potrebbe cambiare, mantenendo il vostro programma o forse quando si ricostruisce e scegliere l'ultima versione di class base.

const_cast viene utilizzato per rimuovere const da un tipo.È anche possibile rimuovere volatile.Se l'oggetto è davvero const quindi il risultato non può essere scritto e di essere ancora ben definito il comportamento.Se, tuttavia, è promosso per const (per essere passato in una const T funzione, quindi const_casting indietro per nonconst è ok.( ho trovato qualche info in più qui)

reinterpret_cast non rimuovere const o volatile da un tipo.

vedi anche

C-stile cast sono davvero il martello di slitta di programmazione, che, fondamentalmente, dire al compilatore che il piolo quadrato, più ci si adatta attraverso questo foro rotondo, non importa cosa.In che senso, reinterpret_cast è molto simile.

Il vantaggio principale vedo in utilizzando il C++in stile cast operatori che consentono di esprimere il vostro intento di meglio e consentire al compilatore ancora per un po ' il controllo sul funzionamento stai chiedendo di eseguire, piuttosto che la one-size-fits-all stile C cast.

Per quanto riguarda const_cast- spesso nella situazione in cui il passaggio di un oggetto attorno a via const riferimento, semplicemente perché le API richiede di fare questo.Dire, hai avuto la funzione di X, attività di tipo C string:

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

All'interno di tale funzione si sta passando il parametro a una funzione C che prevede un char *, anche se non cambiando la stringa.L'unico modo per soddisfare questo sarebbe const_cast str.

Mi piacerebbe essere molto attenti a utilizzare qualsiasi tipo di lancio, spesso questo dimostra che c'è qualcosa che non va con il vostro disegno, ma a volte è necessario convincere il compilatore che il peg è guardando non è come il quadrato, in quanto presuppone.Solo allora si dovrebbe utilizzare il cast operatori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top