Sobes.tech
Senior

Como chamar um método virtual puro?

sobes.tech IA

Resposta da IA

Não é possível chamar diretamente um método virtual puro através de um ponteiro para a classe base com um método abstrato ou através de um objeto dessa classe, pois ele não tem uma definição na classe base.

No entanto, um método virtual puro pode ser chamado a partir do construtor ou destruidor de uma classe derivada, na qual esse método tem uma implementação. Nesse caso, a chamada será resolvida em modo estático, chamando a implementação dessa classe na qual a chamada ocorre.

Exemplo de chamada a partir do construtor de uma classe derivada:

#include <iostream>

class Base {
public:
    virtual void pure_virtual_method() = 0; // Método virtual puro
};

class Derived : public Base {
public:
    void pure_virtual_method() override {
        std::cout << "Implementação em Derived\n";
    }

    Derived() {
        // Chamada de método virtual puro a partir do construtor da classe derivada
        pure_virtual_method();
    }
};

int main() {
    Derived obj; // Criação de um objeto da classe derivada, que chama o construtor
    return 0;
}

Neste exemplo, ao criar o objeto obj da classe Derived, o construtor de Derived é chamado, no qual ocorre a chamada a pure_virtual_method(). Como há uma implementação desse método em Derived, ela será chamada com sucesso.

Tentar chamar um método virtual puro a partir do construtor ou destruidor de uma classe base abstrata, na qual ele é declarado, resultará em comportamento indefinido, pois no momento da execução do construtor ou destruidor da classe base, a vtable ainda não está completamente construída ou já foi destruída, e a implementação correspondente na classe derivada não está acessível.

Também é possível chamar um método virtual puro de uma classe derivada usando a qualificação de escopo (Base::pure_virtual_method()), mas isso só é possível na implementação do método virtual puro na classe derivada, se ela chamar a implementação da classe base (o que não é possível para um método virtual puro) ou outra função que por sua vez chame o método virtual puro (o que também leva a um comportamento indefinido), ou para chamar um método não virtual com o mesmo nome na classe base.

A forma correta de interagir com a lógica apresentada por um método virtual puro é criar um objeto da classe derivada e chamar essa lógica através de um ponteiro ou referência à classe base (polimorfismo).

#include <iostream>

class Base {
public:
    virtual void pure_virtual_method() = 0;
};

class Derived : public Base {
public:
    void pure_virtual_method() override {
        std::cout << "Implementação em Derived via polimorfismo\n";
    }
};

int main() {
    Base* ptr = new Derived(); // Chamada polimórfica
    ptr->pure_virtual_method();
    delete ptr;
    return 0;
}

Assim, "chamar um método virtual puro" no sentido comum (através de um objeto ou ponteiro para a classe base, sem definição) não é possível. A chamada só é possível a partir do construtor ou destruidor da classe derivada com sua implementação, ou indiretamente, através do polimorfismo, criando um objeto da classe derivada.