Sobes.tech
Junior

Wat weet je over het sleutelwoord virtual in C++?

sobes.tech AI

Antwoord van AI

virtual in C++ wordt gebruikt om virtuele functies te declareren in de basisklasse. Dit maakt het mogelijk om polymorfisme op runtime te implementeren.

Toepassing:

  • Definieert een functie in de basisklasse die kan worden overschreven (override) in afgeleide klassen.
  • Wanneer een virtuele functie wordt aangeroepen via een pointer of referentie naar de basisklasse, wordt in werkelijkheid de implementatie van de functie in het object van de afgeleide klasse aangeroepen (als deze is overschreven). Dit gebeurt op runtime via de virtuele functietabel (vtable).

Belangrijke punten:

  • Alleen klasseledenfuncties kunnen virtueel zijn. Globale functies, statische functies en constructors kunnen niet virtueel zijn.
  • Destructors moeten vaak virtueel zijn om geheugenlekken te voorkomen bij het verwijderen van objecten van afgeleide klassen via een pointer naar de basisklasse.
  • Als een functie in de basisklasse virtual is gedeclareerd, blijft deze automatisch virtueel in alle afgeleide klassen, zelfs als het sleutelwoord virtual daar niet expliciet wordt gebruikt (hoewel het gebruik van virtual en override in afgeleide klassen wordt aanbevolen voor duidelijkheid).
  • Pure virtuele functies worden gedeclareerd met = 0 en maken de klasse abstract. Een dergelijke klasse kan niet direct worden geïnstantieerd.

Voorbeeld:

#include <iostream>

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

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

class Derived : public Base {
public:
    void print() override { // Gebruik van override voor expliciete overschrijving
        std::cout << "Van Derived" << std::endl;
    }

    ~Derived() override { // Gebruik van override
        std::cout << "Derived destructor" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived(); // Pointer naar basisklasse wijst naar een afgeleid object

    ptr->print(); // Wordt Derived::print() aangeroepen vanwege virtuele functie
    delete ptr;   // Worden destructors van Derived en daarna van Base aangeroepen vanwege virtuele destructor

    return 0;
}

Gerelateerde concepten:

  • vtable (virtuele functietabel): Tabel van pointers naar virtuele functies van de klasse. Elk object met virtuele functies bevat een onzichtbare pointer (vptr) naar de vtable van zijn klasse.
  • vptr (pointer naar vtable): Nodig om tijdens runtime de op te roepen functie te bepalen.
  • = 0 (zuivere virtuele functie): Geeft aan dat de functie geen implementatie heeft in deze klasse, waardoor de klasse abstract wordt.
  • override (overschrijvingsspecifier): Duidt expliciet aan dat de functie in de afgeleide klasse een virtuele functie van de basisklasse overschrijft. Helpt de compiler fouten te detecteren als de handtekening niet overeenkomt.
  • final (specifier): Verbiedt verdere overschrijving van de virtuele functie of overerving van de klasse.

Kortom: virtual is het belangrijkste mechanisme voor het implementeren van polymorfisme via overerving en dynamische binding in C++.