Sobes.tech
Senior

Jak wywołać czysto wirtualną metodę?

sobes.tech AI

Odpowiedź od AI

Nie można wywołać czystej metody wirtualnej bezpośrednio przez wskaźnik na klasę bazową z metodą abstrakcyjną lub przez obiekt tej klasy, ponieważ nie ma ona definicji w klasie bazowej.

Jednak czysta metoda wirtualna może być wywołana z konstruktora lub destruktora klasy pochodnej, w której ta metoda ma implementację. W takim przypadku wywołanie zostanie rozwiązane w trybie statycznym, wywołując implementację tej klasy, w której następuje wywołanie.

Przykład wywołania z konstruktora klasy pochodnej:

#include <iostream>

class Base {
public:
    virtual void pure_virtual_method() = 0; // Czysta metoda wirtualna
};

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

    Derived() {
        // Wywołanie czystej metody wirtualnej z konstruktora klasy pochodnej
        pure_virtual_method();
    }
};

int main() {
    Derived obj; // Tworzenie obiektu klasy pochodnej, wywołującego konstruktor
    return 0;
}

W tym przykładzie, podczas tworzenia obiektu obj klasy Derived, zostanie wywołany konstruktor Derived, w którym następuje wywołanie pure_virtual_method(). Ponieważ w klasie Derived istnieje jej implementacja, zostanie ona pomyślnie wywołana.

Próba wywołania czystej metody wirtualnej z konstruktora lub destruktora abstrakcyjnej klasy bazowej, w której jest zadeklarowana, spowoduje naruszenie zachowania (undefined behavior), ponieważ w momencie wykonywania konstruktora lub destruktora klasy bazowej vtable jeszcze nie jest w pełni zbudowana lub już została zniszczona, a odpowiednia implementacja w klasie pochodnej jest niedostępna.

Można również wywołać czystą metodę wirtualną z klasy pochodnej, używając kwalifikacji zakresu (Base::pure_virtual_method()), ale jest to możliwe tylko w implementacji czystej metody wirtualnej w klasie pochodnej, jeśli wywołuje ona implementację z klasy bazowej (co dla czystej metody wirtualnej jest niemożliwe) lub inną funkcję, która z kolei wywołuje czystą metodę wirtualną (co również prowadzi do undefined behavior), lub do wywołania niewirtualnej metody o tej samej nazwie z klasy bazowej.

Poprawny sposób interakcji z logiką reprezentowaną przez czystą metodę wirtualną polega na utworzeniu obiektu klasy pochodnej i wywołaniu tej logiki przez wskaźnik lub referencję do klasy bazowej (polimorfizm).

#include <iostream>

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

class Derived : public Base {
public:
    void pure_virtual_method() override {
        std::cout << "Implementacja w Derived przez polimorfizm\n";
    }
};

int main() {
    Base* ptr = new Derived(); // Wywołanie polimorficzne
    ptr->pure_virtual_method();
    delete ptr;
    return 0;
}

W związku z tym, "wywołanie czystej metody wirtualnej" w powszechnym rozumieniu (przez obiekt lub wskaźnik na klasę bazową, nieposiadający definicji) jest niemożliwe. Wywołanie jest możliwe tylko z konstruktora lub destruktora klasy pochodnej z jej implementacją, lub pośrednio, przez polimorfizm, tworząc obiekt klasy pochodnej.