conversão de estilo c ou conversão de estilo c ++

21

Então, o que você usa?

int anInt = (int)aFloat;

ou

int anInt = static_cast<int>(aFloat);
// and its brethren

E, mais importante, por quê?

bastibe
fonte

Respostas:

45

Primeiro, entenda que essas linhas não são equivalentes .

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

O que está acontecendo aqui é que o programador está pedindo ao compilador que faça o possível para fazer o elenco.

A diferença é importante porque o uso do static_cast solicitará apenas um tipo de base "seguro" para converter, onde reinterpret_cast será convertido em qualquer coisa, possivelmente apenas mapeando o layout de memória desejado sobre a memória do objeto especificado.

Portanto, como o "filtro" não é o mesmo, o uso de conversão específica é mais claro e seguro do que a conversão C, se você confiar no compilador (ou no tempo de execução, se você usar dynamic_cast) para lhe dizer onde você fez algo errado. , evitando C cast e reinterepret_cast.

Agora que isso está mais claro, existe outra coisa: static_cast, reinterpret_cast, const_cast e dynamic_cast são mais fáceis de pesquisar .

E o ponto final: eles são feios . Isso é desejado. Código potencialmente defeituoso, cheiro de código, "truques" óbvios que podem gerar bugs são mais fáceis de rastrear quando associados a aparência feia. Código incorreto deve ser feio .

Isso é "por design". E isso permite que o desenvolvedor saiba onde ele poderia ter feito as coisas melhor (evitando totalmente os lançamentos, se não for realmente necessário) e onde está tudo bem, mas é "documentado" no código "marcando" como feio.

Um motivo secundário para a introdução do elenco de novo estilo foi que é muito difícil encontrar elencos no estilo C em um programa. Por exemplo, você não pode procurar por conversões usando um editor ou processador de texto comum. Essa quase invisibilidade dos elencos em estilo C é especialmente lamentável porque eles são potencialmente prejudiciais. Uma operação feia deve ter uma forma sintática feia.Essa observação foi parte do motivo da escolha da sintaxe para os elencos de novo estilo. Um outro motivo foi o fato de as conversões de novo estilo corresponderem à notação do modelo, para que os programadores possam escrever suas próprias conversões, especialmente as verificadas em tempo de execução.

Talvez, como o static_cast seja tão feio e relativamente difícil de digitar, é mais provável que você pense duas vezes antes de usar um? Isso seria bom, porque as conversões são realmente evitáveis ​​no C ++ moderno.

Fonte: Bjarne Stroustrup (criador do C ++)

Klaim
fonte
2
Eu diminuiria isso se tivesse mais alguns pontos, mas infelizmente não posso. As conversões no estilo c NÃO são equivalentes a reinterpret_cast. Considere reinterpret_cast<int>(double);. É inteiramente possível converter um double para um int com um estilo c, mas não é possível fazê-lo com reinterpret_cast. Vejo que o Timbo já apontou isso para você e você disse que iria consertá-lo, mas quatro anos depois ele permanece incorreto. Ainda assim, eu votaria em você se isso fosse corrigido, pois existem razões perfeitamente válidas para a necessidade de usar um elenco. Aqui está uma resposta melhor: stackoverflow.com/a/332086/3878168
Yay295 3/15
36

As conversões em C ++ são mais restritivas (exprima melhor sua intenção e facilite a revisão de código etc.). Eles também são muito mais fáceis de pesquisar, se você precisar.

Bruce Stephens
fonte
10
... e é mais provável que eles façam o que você pretende. ;-)
Macke
7
E eles são muito mais para digitar, oferecendo mais um motivo para corrigir seus tipos sem a necessidade de transmissões.
Michael Kohne
7
E são feias como um recurso, tornando óbvio onde no código pode haver pontos de melhoria ou casos especiais que podem exigir documentação. - edit: wow Acabei de descobrir que também respondi a esta pergunta! XD
Klaim
Agora, por que eu iria querer procurá-los?
Deduplicator
@Duplicador Há muitas razões pelas quais você pode querer saber onde as transmissões estão acontecendo em uma base de código. Por exemplo, ao caçar bugs que podem estar associados à transmissão (em particular ao desenvolver desenvolvimento de plataforma cruzada).
Klaim
13

Opção C: um elenco "estilo C ++", porque é indistinguível de uma construção:

int anInt = int(aFloat);

ou até:

int anInt(aFloat);

Além disso, além desses casos triviais com primitivos, que são bem entendidos, eu prefiro usar x_cast <> s sobre elencos no estilo C. Existem três razões pelas quais:

  • Eles definem mais estritamente a operação que o programador estava tentando executar.

  • Eles podem executar ações que as transmissões no estilo C não podem (especialmente no caso de dynamic_cast <>, que pode transmitir entre as ramificações de uma cadeia de herança múltipla).

  • Eles são feios . Eles declaram em voz alta que o programador está trabalhando contra o sistema de tipos. Nesse caso, é uma coisa boa .

Kaz Dragon
fonte
7

Se escrever código em C, use uma conversão C. Se estiver escrevendo em C ++, use uma conversão de C ++.

Enquanto a maioria das transmissões quebra a segurança de tipo adequada, as de C ++ são mais restritivas e, portanto, você é um pouco menos inseguro do que seria com uma transmissão em C.

Eu posso tolerar alguém usando (T *) NULL embora para forçar uma sobrecarga ...

CashCow
fonte
7

Eu tenho algumas regras sobre conversões no estilo C / C ++:

  1. Desaplicar uma const deve sempre usar a const_cast. Por razões óbvias. Infelizmente, minha regra sobre a desaplicação de uma const que faz com que o teclado alcance e quebre o dedo do programador não foi aprovada.
  2. Qualquer uma das travessuras no estilo de manipulação de bits que os programadores fazem quando se trata de metal deve usar reinterpret_cast. É realmente o tipo de elenco que C não possui: finja que os bits deste número inteiro são na verdade bits de um float. Isso evita desagradáveis ​​como (int)(*(int*)(&floatVar)).
  3. Se você digitar as palavras " dynamic_cast", pare e reavalie sua hierarquia e design de classe polimórficos. Continue reavaliando o design da hierarquia da sua classe até poder excluir essas palavras.
  4. Não se preocupe static_cast.

O raciocínio por trás do nº 4 é simplesmente que isso não importa. As circunstâncias que não se enquadram nas outras regras são óbvias ou realmente de baixo nível. Uma conversão bem compreendida de tipos simples como int-to-float não deve precisar de sintaxe especial. E se você está nas profundezas feias de alguma coisa, bem, você está nas entranhas profundas e feias de alguma coisa. Não há necessidade de chamar a atenção para o fato de que "aqui existem dragões", já que os dentes, garras e fogo já o revelaram.

Nicol Bolas
fonte
1
dynamic_casté uma ferramenta perfeitamente válida. Raramente útil, admito, mas está longe de Satanás de coisas como variáveis ​​globais. No entanto, principalmente, eu diminuí o voto porque você não respondeu à pergunta , que era sobre o uso ou não de elencos no estilo C.
DeadMG
2
@DeadMG: Eu falei sobre elencos em estilo C. O último parágrafo inteiro justifica lançamentos no estilo C em favor do static_cast.
Nicol Bolas
"Infelizmente, minha regra sobre a desaplicação de uma const que faz com que o teclado alcance e quebre o dedo do programador não foi aprovada." Tecnicamente, é realmente legal para o compilador fazer isso acontecer. Como é legal para o compilador fazer com que demônios voem do seu nariz .
Pharap 18/09
3

Depende realmente do idioma em que estou trabalhando, já que você sabe o que eles dizem: em Roma, fale romano. Portanto, se estou programando em C, tento usar os recursos C ao máximo, mas se estiver programando em C ++, uso os recursos C ++ ao máximo, mesmo que algumas pessoas não gostem dessa abordagem porque eles dizem que torna o código "menos portátil", digo que não me importo, estou em C ++ e programação em C ++, e preciso de um compilador totalmente compatível com C ++ para compilar código, caso contrário, eu estaria trabalhando com algo diferente em primeiro lugar.

Coiote21
fonte
Ele realmente não funciona tentando usar C ++ - elencos estilo em C ;-)
Steve314
3

static_cast etc foram inventados devido a problemas com as conversões de estilo C quando usadas em modelos. Se você estiver escrevendo um modelo ou se seu código for posteriormente convertido em um modelo, é uma boa ideia usar conversões no estilo C ++. O motivo é que as conversões no estilo C ++ expressam melhor a intenção, portanto elas fornecerão os resultados esperados nos casos em que as conversões no estilo C farão a coisa errada (determinados tipos como parâmetros do modelo).

Fora isso, digo que use conversões no estilo C ++, se você tiver um problema específico que precise delas - dynamic_cast é o mais comum, mas mesmo isso provavelmente não é algo comum todos os dias.

Qualquer outra coisa, e um elenco no estilo C pode ser um pouco menos confuso e facilitar a legibilidade, ou talvez não dependendo da familiaridade do leitor com esse estilo nos dias de hoje. Na minha opinião, não é realmente importante, principalmente uma preferência pessoal, embora não se surpreenda se algumas pessoas não gostarem do estilo C.

Nota final - se você precisar de tantos elencos que isso seja um grande negócio, provavelmente está fazendo outra coisa errada. Existem exceções em alguns casos, mas a maioria dos códigos de alto nível não deve precisar de muitas (se houver) transmissões.

Steve314
fonte