Sobes.tech
Junior

O que você sabe sobre a palavra-chave virtual em C++?

sobes.tech IA

Resposta da IA

virtual em C++ é usado para declarar funções virtuais na classe base. Isso permite implementar o polimorfismo em tempo de execução (polimorfismo em tempo de execução).

Aplicação:

  • Define uma função na classe base que pode ser sobrescrita (override) em classes derivadas.
  • Quando uma função virtual é chamada através de um ponteiro ou referência à classe base, na realidade é a implementação da função no objeto da classe derivada que é chamada (se foi sobrescrita). Isso acontece em tempo de execução através da tabela de funções virtuais (vtable).

Pontos principais:

  • Apenas funções membro de classe podem ser virtuais. Funções globais, funções membro estáticas e construtores não podem ser virtuais.
  • Os destrutores podem e frequentemente devem ser virtuais para evitar vazamentos de memória ao eliminar objetos de classes derivadas através de um ponteiro para a classe base.
  • Se uma função for declarada virtual na classe base, ela permanece automaticamente virtual em todas as classes derivadas, mesmo que a palavra-chave virtual não seja usada explicitamente lá (embora seja recomendado usar virtual e override em classes derivadas para maior clareza).
  • Funções virtuais puras são declaradas com = 0 e tornam a classe abstrata. Essa classe não pode ser instanciada diretamente.

Exemplo:

#include <iostream>

class Base {
public:
    virtual void print() {
        std::cout << "De Base" << std::endl;
    }

    virtual ~Base() {
        std::cout << "Destruidor de Base" << std::endl;
    }
};

class Derived : public Base {
public:
    void print() override { // Uso de override para indicar claramente a sobrescrita
        std::cout << "De Derived" << std::endl;
    }

    ~Derived() override { // Uso de override
        std::cout << "Destruidor de Derived" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived(); // Pontero para a classe base aponta para um objeto derivado

    ptr->print(); // Chama Derived::print() devido à função virtual
    delete ptr;   // Chama os destrutores de Derived e depois de Base devido ao destrutor virtual

    return 0;
}

Conceitos relacionados:

  • vtable (tabela de funções virtuais): Tabela de ponteiros para funções virtuais da classe. Cada objeto com funções virtuais contém um ponteiro invisível (vptr) para a vtable de sua classe.
  • vptr (ponteiro para vtable): Necessário para determinar qual função chamar em tempo de execução.
  • = 0 (função virtual pura): Indica que a função não tem implementação nesta classe, tornando-a abstrata.
  • override (especificador de sobrescrita): Indica explicitamente que a função na classe derivada sobrescreve uma função virtual da base. Ajuda o compilador a detectar erros se a assinatura não coincidir.
  • final (especificador): Proíbe futuras sobrescritas de funções virtuais ou herança da classe.

Resumindo: virtual é o mecanismo principal para implementar o polimorfismo através de herança e ligação dinâmica em C++.