Sobes.tech
Junior

Co víte o klíčovém slovu virtual v C++?

sobes.tech AI

Odpověď od AI

virtual v C++ slouží k deklaraci virtuálních funkcí v základní třídě. To umožňuje implementaci polymorfismu během běhu (runtime polymorphism).

Použití:

  • Definuje funkci v základní třídě, kterou lze přepsat (override) v odvozených třídách.
  • Při volání virtuální funkce přes ukazatel nebo odkaz na základní třídu je skutečně volána implementace funkce v objektu odvozené třídy (pokud je tam přepsána). To se děje během běhu pomocí tabulky virtuálních funkcí (vtable).

Hlavní body:

  • Virtuální mohou být pouze členské funkce třídy. Globální funkce, statické členské funkce a konstruktory nemohou být virtuální.
  • Destruktory mohou a často by měly být virtuální, aby se zabránilo únikům paměti při mazání objektů odvozených tříd přes ukazatel na základní třídu.
  • Pokud je funkce deklarována virtual v základní třídě, zůstává automaticky virtuální ve všech odvozených třídách, i když tam není explicitně použito virtual (ačkoliv doporučuje se to uvádět explicitně pro jasnost).
  • Čistě virtuální funkce jsou deklarovány s = 0 a činí třídu abstraktní. Taková třída nemůže být přímo instanciována.

Příklad:

#include <iostream>

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

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

class Derived : public Base {
public:
    void print() override { // Použití override pro jasné označení přepsání
        std::cout << "From Derived" << std::endl;
    }

    ~Derived() override { // Použití override
        std::cout << "Derived destructor" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived(); // Ukazatel na základní třídu ukazuje na objekt odvozené

    ptr->print(); // Volá se Derived::print() kvůli virtuální funkci
    delete ptr;   // Volají se destruktory Derived a poté Base kvůli virtuálnímu destruktoru

    return 0;
}

Související pojmy:

  • vtable (tabulka virtuálních funkcí): Tabulka ukazatelů na virtuální funkce třídy. Každý objekt s virtuálními funkcemi obsahuje neviditelný ukazatel (vptr) na vtable své třídy.
  • vptr (ukazatel na vtable): Nutný pro určení volané funkce během běhu.
  • = 0 (čistá virtuální funkce): Znamená, že funkce nemá implementaci v této třídě, čímž se stává abstraktní.
  • override (přepsání): Výslovně označuje, že funkce v odvozené třídě přepisuje virtuální funkci základní třídy. Pomáhá kompilátoru najít chyby, pokud se signatura funkce neshoduje.
  • final (konec): Zakazuje další přepsání virtuální funkce nebo dědění od třídy.

Stručně: virtual je hlavní mechanismus pro implementaci polymorfismu přes dědičnost a dynamické vázání funkcí v C++.