Virtuální funkce

Virtuální funkce (někdy nazývané virtuální metoda) je funkce pracující s instancí třídy, jejíž chování je určeno definicí funkce třídy instance nezávisle na typu ukazatele, který na instanci ukazuje. Virtuální funkce tvoří základ pro polymorfismus (spíš tvoří jeden ze způsobů implementace polymorfismu), což je jeden ze základních znaků objektově orientovaného programování.

V některých programovacích jazycích (například v Javě) jsou metody instancí implicitně virtuální. Nechcete-li, aby byla metoda definována jak virtuální, musíte ji definovaným způsobem označit.

V jiných programovacích jazycích (např. v C++ nebo v C#) naopak funkce implicitně nejsou virtuální a chete-li je definovat jako virtuální, musíte je definovaným způsobem označit.

Metody tříd z prinicipu virtuální být nemohou, leda by třída byla definována jako řádný objekt, jenž je instancí nějaké třídy tříd, jak je tomu např. v jazyku Smalltalk.

Popis

Koncept virtuální funkce řeší následující problém: Mějme třídu B odvozenou od třídy A. Máme-li ukazatel na instanci třídy A, může ukazovat jak na instanci třídy A, tak i na instanci třídy B. Ve chvíli překladu programu ale nemusí být jasné (a ani odvoditelné), na instanci které třídy ukazatel ukazuje. Pokud není funkce virtuální, vykoná se funkce třídy A i v tom případě, kdy bude ukazatel ukazovat na instanci třídy B. Virtuální funkce řeší tento problém tím, že se buď 1. podívá na typ objektu (dynamický výběr, dynamic dispatch) nebo 2. vybírá funkci z dat konkrétního objektu (tabulka virtuálních metod), a až poté vybranou funkci spouští. Toto vede k mírnému snížení výkonu aplikace, není proto vždy vhodné použít virtuální funkce.

Příklad

# include <iostream> //c++
using namespace std;

class Utvar
{
   public:
   virtual void Kresli() { cout << "Kresli utvar..." << endl; }
};

class Kruh : public Utvar
{
   public:
   void Kresli() { cout << "Kresli kruh..." << endl; }
};

class Jehlan : public Utvar
{
   public:
   void Kresli() { cout << "Kresli jehlan..." << endl; }
};

int main()
{
  Utvar* uUtvar = new Utvar();
  Utvar* uKruh = new Kruh();
  Utvar* uJehlan = new Jehlan();

  uUtvar->Kresli();
  uKruh->Kresli();
  uJehlan->Kresli();

  delete uUtvar;
  delete uKruh;
  delete uJehlan;

  return 0;
}

Výstup s virtuální metodou Kresli:

Kresli utvar...
Kresli kruh...
Kresli jehlan...

Výstup kdyby metoda Kresli nebyla deklarována jako virtuální:

Kresli utvar...
Kresli utvar...
Kresli utvar...