Funções Virtuais em C++: por que um iniciante precisa delas?

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

Funções Virtuais em C++: por que não dá para viver sem elas?

\n\n

Imagine que você é um diretor filmando um filme sobre animais. Você tem um roteiro: "Todos os animais emitem um som". Você filma uma cena com um cachorro — ele late. Uma cena com um gato — ele mia. Tudo lógico. Agora imagine que seu assistente (o compilador) traz uma caixa de animais de brinquedo e diz: "Filme!". Você aperta o botão, e o brinquedo... fica em silêncio. Por quê? Porque você esqueceu as funções virtuais.

\n\n

Na programação em C++, esse problema aparece o tempo todo. Você escreve a classe "Animal", dentro dela o método sound(). Depois cria as classes "Cachorro" e "Gato", que herdam de "Animal". E parece que está tudo bem, até você tentar trabalhar com esses objetos através de um ponteiro para a classe base. É aí que descobre que o C++, por padrão, chama o método da classe base, e não o sobrescrito na classe derivada. As funções virtuais resolvem esse problema de uma vez por todas.

\n\n

Neste artigo, vamos detalhar o que são funções virtuais, para que servem, como funcionam internamente e por que são indispensáveis no C++ moderno.

\n\n

O que é uma função virtual em termos simples

\n\n

Função virtual é um método de classe que você marca com a palavra-chave virtual. Essa função pode ser sobrescrita em classes derivadas, e, ao ser chamada através de um ponteiro ou referência para a classe base, a versão da classe derivada será executada.

\n\n

Parece complicado? Vamos a um exemplo da vida real. Imagine um controle remoto para robôs. Você tem uma classe base "Robô" com o método doWork(). Existem um robô aspirador e um robô entregador. Se você aperta o botão "Trabalhar", os algoritmos correspondentes devem ser executados: o aspirador começa a limpar, o entregador começa a entregar um pacote. Sem funções virtuais, você apertaria o botão e o robô simplesmente ficaria parado (o método da classe base seria chamado).

\n\n

Em C++, as funções virtuais são a base do polimorfismo. O polimorfismo permite trabalhar de forma uniforme com objetos de tipos diferentes, desde que eles herdem de um ancestral comum.

\n\n

O problema sem funções virtuais: um exemplo prático

\n\n

Vamos ver o que acontece se não usarmos virtual.

\n\n
#include <iostream>\n#include <vector>\n\nclass Animal {\npublic:\n    void sound() {\n        std::cout << "Some generic animal sound" << std::endl;\n    }\n};\n\nclass Dog : public Animal {\npublic:\n    void sound() {\n        std::cout << "Woof! Woof!" << std::endl;\n    }\n};\n\nclass Cat : public Animal {\npublic:\n    void sound() {\n        std::cout << "Meow!" << std::endl;\n    }\n};\n\nint main() {\n    std::vector<Animal*> animals;\n    animals.push_back(new Dog());\n    animals.push_back(new Cat());\n\n    for (Animal* a : animals) {\n        a->sound(); // O que será exibido?\n    }\n\n    // Limpeza de memória\n    for (Animal* a : animals) delete a;\n\n    return 0;\n}\n
\n\n

Execute este código. Você verá:

\n
Some generic animal sound\nSome generic animal sound\n
\n\n

Por quê? Porque o compilador olha para o tipo do ponteiro (Animal*), e não para o objeto real. Ele chama o método da classe base. Isso é chamado de ligação antecipada (early binding) — a decisão sobre qual método chamar é tomada em tempo de compilação.

\n\n

Nós queremos ligação tardia (late binding) — que a decisão seja tomada durante a execução do programa, dependendo do tipo do objeto. É exatamente isso que as funções virtuais proporcionam.

\n\n

Solução: adicionando virtual

\n\n

Vamos corrigir o exemplo adicionando a palavra-chave virtual.

\n\n
class Animal {\npublic:\n    virtual void sound() {  // Adicionamos virtual\n        std::cout << "Some generic animal sound" <<                

Blogs

Book Recommendations