Sobes.tech
Junior

Cosa sai della parola chiave virtuale in C++?

sobes.tech AI

Risposta dell'AI

virtual in C++ viene utilizzato per dichiarare funzioni virtuali nella classe base. Questo consente di implementare il polimorfismo in fase di esecuzione (polimorfismo runtime).

Applicazione:

  • Definisce una funzione nella classe base che può essere sovrascritta (override) nelle classi derivate.
  • Quando una funzione virtuale viene chiamata tramite un puntatore o riferimento alla classe base, in realtà viene chiamata l'implementazione della funzione nell'oggetto della classe derivata (se è stata sovrascritta). Questo avviene in fase di esecuzione tramite la tabella delle funzioni virtuali (vtable).

Punti chiave:

  • Solo le funzioni membro di classe possono essere virtuali. Le funzioni globali, le funzioni membro statiche e i costruttori non possono essere virtuali.
  • I distruttori possono e devono spesso essere virtuali per evitare perdite di memoria durante l'eliminazione di oggetti di classi derivate tramite un puntatore alla classe base.
  • Se una funzione è dichiarata virtual nella classe base, rimane automaticamente virtuale in tutte le classi derivate, anche se non si utilizza esplicitamente la parola chiave virtual (anche se si consiglia di usare virtual e override nelle classi derivate per maggiore chiarezza).
  • Le funzioni virtuali pure sono dichiarate con = 0 e rendono la classe astratta. Una tale classe non può essere istanziata direttamente.

Esempio:

#include <iostream>

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

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

class Derived : public Base {
public:
    void print() override { // Uso di override per indicare chiaramente la sovrascrittura
        std::cout << "Da Derived" << std::endl;
    }

    ~Derived() override { // Uso di override
        std::cout << "Distruttore di Derived" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived(); // Puntatore alla classe base che punta a un oggetto derivato

    ptr->print(); // Viene chiamato Derived::print() grazie alla funzione virtuale
    delete ptr;   // Vengono chiamati i distruttori di Derived e poi di Base grazie al distruttore virtuale

    return 0;
}

Concetti correlati:

  • vtable (tabella delle funzioni virtuali): Tabella di puntatori alle funzioni virtuali della classe. Ogni oggetto con funzioni virtuali contiene un puntatore invisibile (vptr) alla vtable della sua classe.
  • vptr (puntatore alla vtable): Necessario per determinare quale funzione chiamare in fase di esecuzione.
  • = 0 (funzione virtuale pura): Indica che la funzione non ha implementazione in questa classe, rendendola astratta.
  • override (specificatore di sovrascrittura): Indica esplicitamente che la funzione nella classe derivata sovrascrive una funzione virtuale della classe base. Aiuta il compilatore a trovare errori se la firma non corrisponde.
  • final (specificatore): Impedisce ulteriori sovrascritture di funzioni virtuali o ereditarietà dalla classe.

In breve: virtual è il meccanismo principale per implementare il polimorfismo tramite ereditarietà e binding dinamico in C++.