Pergunta

Estou certo em assumir que C-estilo de lança (que são desencorajados) são nada, mas reinterpret_casts?Usando o último é visualmente impressionante e fácil de pesquisar quando se olha para o desagradável lança, e, portanto, recomenda-se sobre o C-estilo de lança?

Se lançando de si a const usando const_cast e a escrita originalmente para um objeto const não está definida, qual é o propósito de const_cast?

Nota: Eu sei que Bjarne, com razão, condena operações de fundição de que eles são seguros, e vai mesmo ao ponto de afirmar que "Uma feio a operação deve ter um feio sintática forma." e, consequentemente, o detalhamento de fundição de operadores em C++.Então, eu vou tentar minimizar o seu uso.Promessa.:)

Foi útil?

Solução

Não.C o elenco pode fazer o equivalente a um const_cast, um static_cast, um reinterpret_cast, ou uma combinação destes.No caso em que isso não era o bastante, ele pode também fazer pelo menos um pequeno truque que nenhum a combinação da mais recente da lança pode fazer em tudo!

Você pode usar const_cast com resultados predefinidos se a variável original é definido sem const, mas tudo que você tem é um const ponteiro ou referência a esse objeto.OTOH, se você acha que você tem uma boa razão para usar um const_cast, as chances são de que você deve realmente olhar para cima mutable em vez disso.

Editar:Acho que eu deveria ter dito isso direito, mas um estilo de C elenco pode converter para um inacessíveis classe base.Por exemplo, considerar algo como:

[Editar:Estou atualizando o código para algo que vai compilar e (geralmente) demonstrar o 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;
}

O código usando o reinterpret_casts irá compilar -- mas tentando usar o resultado (de pelo menos uma das duas) vai causar um grande problema.O reinterpret_cast leva a base endereço do objeto derivado e tenta tratá-lo como se fosse especificado o tipo de objecto de base-e desde que (mais) um objecto de base, na verdade, pode existir nesse endereço, tentando tratá-lo como o outro pode/vai causar grandes problemas.Editar:Neste caso, as aulas são essencialmente idênticos, exceto pelo que eles impressão, então, apesar de qualquer coisa poderia acontecer, com a maioria dos compiladores, as duas últimas irá imprimir "da base de dados de 1".O reinterpret_cast leva tudo o que acontece naquele endereço e tenta usá-lo como o tipo especificado.Neste caso, eu (tentei) fazer o que fazer algo inofensivo, mas visível.No código real, o resultado provavelmente não será tão bonita.

O C-estilo elenco vai funcionar como um static_cast seria se o código tinha usado público herança, em vez de privada -- i.e.ele está ciente de onde a classe derivada de cada objeto de classe base "vida", e ajusta o resultado, de modo que cada ponteiro resultante irá funcionar porque foi ajustado para o ponto no lugar certo.

Outras dicas

Não, C-estilo lança pode atuar como reinterpret_casts, const-casts ou static_casts, dependendo da situação.É por isso que eles são desencorajados - você consulte um estilo de C expressos no código e precisa de olhar para os detalhes, para ver o que ele vai fazer.Por exemplo:

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

Lembre-se, que uma constante de elenco pode estar atuando em algo diferente, em seguida, o original identificador:

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

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

Assim, enquanto doit está lançando de si a const, neste exemplo subjacente de seqüência de caracteres não é constante, de modo nenhum comportamento indefinido.

Atualização

Ok, aqui está um exemplo melhor de quando usar const_cast não é completamente inútil.Nós começar com uma base de classe com uma função virtual que tem uma constante de parâmetro:

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

e agora que você quiser substituir a função virtual.

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

Por causa da lógica/estrutura de seu código, você sabe que child::doit só vai ser chamado com não-const cadeias de caracteres (e class base não está sob o seu controle, portanto, você não pode modificar nem alterar a assinatura de child::doit porque então ele não vai mais substituir base::doit).Neste caso, é seguro para lançar fora const.

Sim, isso é arriscado.Talvez quando você escreve, é verdade que a execução nunca vai chegar child::doit com um não-const string e o código é válido.Mas o que poderia alterar, mantendo o seu programa ou, talvez, quando você reconstruir e pegar a versão mais recente do class base.

const_cast é usado para remover const a partir de um tipo.Ele também pode remover volatile.Se o objeto realmente é const em seguida, o resultado não pode ser gravado e ainda ser bem definidos de comportamento.Se, no entanto, ele é promovido para const (sendo passado para um const T função e, em seguida, const_casting-lo de volta para nãoconst é ok.( eu encontrei mais algumas informações aqui)

reinterpret_cast não remover const ou volatile a partir de um tipo.

veja também

C-estilo de lança são realmente a marreta de programação - você basicamente informar ao compilador que o pino quadrado em cima de lá vai caber através deste orifício redondo, não importa o que.Nesse sentido, reinterpret_cast é muito semelhante.

A principal vantagem que eu vejo em usar o C++estilo elenco operadores que eles permitem que você expresse sua intenção de melhor e permitir que o compilador ainda para alguns verificar a operação que você está pedindo a ele para realizar, ao invés do que o one-size-fits-all estilo C elenco.

Sobre const_cast- muitas vezes você entrar na situação em que você está passando um objeto em torno de via constante de referência, simplesmente porque a API requer que você para fazer isso.Dizer, você tem função de X que as tarefas de um C-estilo de seqüência de caracteres:

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

Dentro da função que você está passando o parâmetro para uma função C que espera um char *, apesar de não alterar a seqüência de caracteres.A única forma de acomodar esta seria const_cast str.

Eu teria muito cuidado com a utilização de qualquer tipo de elenco, muitas vezes, isso mostra que há algo não muito certo com o seu design, mas às vezes você tem que convencer o compilador que o peg ele olha não é tão quadrado como ele supõe.Só então você deve usar o elenco operadores.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top