static_cast, dynamic_cast, const_cast, reinterpret_cast: quando usar cada um?

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que o C++ não perdoa erros de conversão de tipos?



Olá, amigo! Se você já programou em C++ pelo menos uma vez, com certeza já se deparou com uma situação em que o compilador reclama de incompatibilidade de tipos. E aí, provavelmente, você se lembra do bom e velho cast no estilo C: (int)x. Funciona? Sim. Seguro? Não. Profissional? Ainda menos.



Em C++, existem quatro operadores de conversão embutidos, e cada um resolve seu próprio problema: static_cast, dynamic_cast, const_cast e reinterpret_cast. Usá-los corretamente significa escrever código que não só funciona, mas também é compreensível para outros desenvolvedores. E mais: não falha em tempo de execução com erros misteriosos.



Neste tutorial, vamos analisar cada cast com exemplos reais, entender quando usar cada um e quando é melhor nem fazer a conversão. Vamos nessa!



static_cast: seu amigo confiável para conversões comuns



static_cast é o cast mais popular e seguro. Ele é usado para conversões explícitas entre tipos relacionados: tipos numéricos, ponteiros para cima/baixo na hierarquia de herança (sem verificação em tempo de execução), enumerações para inteiros e vice-versa.



Quando usar static_cast?

  • Conversão de int para double (e vice-versa).
  • Conversão de ponteiros dentro da mesma hierarquia de classes (upcast — seguro, downcast — precisa ter certeza).
  • Conversão de void* para um tipo específico.
  • Chamada de construtores explícitos ou operadores de conversão.


Exemplo:

double pi = 3.14159;int approx = static_cast<int>(pi); // 3

class Base { public: virtual ~Base() = default; };class Derived : public Base { public: void foo() {} };

Base* b = new Derived;Derived* d = static_cast<Derived*>(b); // OK, mas sem verificaçãod->foo();delete b;


Importante: static_cast não faz verificação de tipos em tempo de execução. Se você tem certeza de que o objeto é realmente daquele tipo, use-o. Caso contrário, veja o dynamic_cast.



dynamic_cast: downcast seguro com verificação



dynamic_cast é o único cast que funciona apenas com classes polimórficas (deve haver pelo menos uma função virtual). Ele verifica em tempo de execução se é possível converter o ponteiro/referência com segurança. Se não for, retorna nullptr (para ponteiros) ou lança std::bad_cast (para referências).



Quando usar dynamic_cast?

  • Quando você não tem certeza se o objeto é exatamente do tipo derivado.
  • Ao trabalhar com contêineres heterogêneos (por exemplo, vector de Base*).
  • Em padrões de projeto (como Visitor).


Exemplo:

class Base { public: virtual ~Base() = default; };class Derived : public Base { public: void specific() {} };class Other : public Base {};

vector<Base*> objects = {new Derived, new Other, new Derived};

for (Base* obj : objects) { Derived* d = dynamic_cast<Derived*>(obj); if (d) { d->specific(); // seguro apenas para Derived }}


Desvantagem: dynamic_cast é mais lento que static_cast, pois requer RTTI (Run-Time Type Information). Não abuse dele em trechos críticos de desempenho.



const_cast: quando remover a constância (mas com cuidado!)



const_cast é o único cast que pode remover (ou adicionar) qualificadores cv (const, volatile). Parece legal, mas na prática é usado raramente e apenas em casos extremos.



Para que ele serve? Às vezes você recebe uma referência constante para um objeto, mas precisa chamar uma função antiga que não está marcada como const, embora ela não modifique o objeto. Ou ao trabalhar com bibliotecas C.



Exemplo (correto):

void printInt(const int* p) {    // antigo                

Blogs

Book Recommendations