Sobes.tech
Senior

Jak zavolat čistou virtuální metodu?

sobes.tech AI

Odpověď od AI

Není možné přímo volat čistou virtuální metodu přes ukazatel na abstraktní základní třídu nebo přes objekt této třídy, protože nemá definici v základní třídě.

Nicméně, čistá virtuální metoda může být volána z konstruktoru nebo destruktoru odvozené třídy, ve které má tato metoda implementaci. Při tom bude volání povoleno v statickém režimu a bude volena implementace té třídy, ve které je volání provedeno.

Příklad volání z konstruktoru odvozené třídy:

#include <iostream>

class Base {
public:
    virtual void pure_virtual_method() = 0; // Čistá virtuální metoda
};

class Derived : public Base {
public:
    void pure_virtual_method() override {
        std::cout << "Implementace v Derived\n";
    }

    Derived() {
        // Volání čisté virtuální metody z konstruktoru odvozené třídy
        pure_virtual_method();
    }
};

int main() {
    Derived obj; // Vytvoření objektu odvozené třídy, volajícího konstruktor
    return 0;
}

V tomto příkladu, při vytvoření objektu obj třídy Derived, bude zavolán konstruktor Derived, ve kterém dojde k volání pure_virtual_method(). Protože v třídě Derived je tato metoda implementována, bude úspěšně volána.

Pokud se pokusíte volat čistou virtuální metodu z konstruktoru nebo destruktoru abstraktní základní třídy, ve které je deklarována, dojde k chování nevymezené (undefined behavior), protože v době provádění konstruktoru nebo destruktoru ještě není vtable základní třídy plně sestavena nebo je již zničena, a odpovídající implementace v odvozené třídě není dostupná.

Také je možné volat čistou virtuální metodu z odvozené třídy pomocí kvalifikace oblasti viditelnosti (Base::pure_virtual_method()), ale to je možné pouze z implementace čisté virtuální metody v odvozené třídě, pokud volá implementaci z základní třídy (čehož u čisté virtuální metody není), nebo jinou funkci, která volá čistou virtuální metodu (což také vede k nevymezenému chování), nebo pro volání nevirtuální metody se stejným jménem z základní třídy.

Správný způsob práce s logikou, reprezentovanou čistou virtuální metodou, je vytvoření objektu odvozené třídy a volání této logiky přes ukazatel nebo odkaz na základní třídu (polymorfismus).

#include <iostream>

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

class Derived : public Base {
public:
    void pure_virtual_method() override {
        std::cout << "Implementace v Derived přes polymorfismus\n";
    }
};

int main() {
    Base* ptr = new Derived(); // Polymorfní volání
    ptr->pure_virtual_method();
    delete ptr;
    return 0;
}

Tedy, "volání čisté virtuální metody" v obvyklém smyslu (přes objekt nebo ukazatel na základní třídu, která nemá definici) není možné. Volání je možné pouze z konstruktoru nebo destruktoru odvozené třídy s její implementací, nebo nepřímo přes polymorfismus, vytvořením objektu odvozené třídy.