override, final în C++

override cere compilatorului să verifice că metoda chiar suprascrie una virtuală; final oprește suprascrierea sau moștenirea mai departe.

Sintaxă
void metoda() override;          // suprascrie o metodă virtuală
void metoda() final;             // nu mai poate fi suprascrisă
class Nume final { ... };        // nu se poate moșteni din ea

Ce face override, final

override, pus după o metodă dintr-o clasă derivată, spune „aceasta suprascrie o metodă virtuală din bază”. Dacă nu există o astfel de metodă (nume greșit, alt tip de parametru, const uitat), compilatorul dă eroare. Fără override, greșeala trece neobservată și se creează pur și simplu o metodă nouă.

final după o metodă virtuală interzice suprascrierea ei în clasele derivate mai departe. final după numele clasei interzice moștenirea din ea.

override și final nu sunt cuvinte rezervate obișnuite, ci „identificatori cu sens special”: au acest rol doar în aceste poziții, deci poți avea în continuare o variabilă numită final.

Exemple

Exemplul 1: override în practică

#include <print>

struct Notificare {
    virtual ~Notificare() = default;
    virtual void trimite(const char* text) const { std::println("[generic] {}", text); }
};

struct Sms : Notificare {
    void trimite(const char* text) const override { std::println("[SMS] {}", text); }
};

struct Email : Notificare {
    void trimite(const char* text) const override { std::println("[e-mail] {}", text); }
};

int main() {
    Sms sms;
    Email email;
    const Notificare* canale[] = {&sms, &email};
    for (const auto* c : canale) {
        c->trimite("Comanda a fost livrată");
    }
}

Rezultat

[SMS] Comanda a fost livrată
[e-mail] Comanda a fost livrată

Exemplul 2: final pe metodă și pe clasă

Nicio clasă nu poate moșteni din Admin, iar clasele derivate din Utilizator nu mai pot suprascrie id(). Încercările ar da erori de compilare.

#include <print>

struct Cont {
    virtual ~Cont() = default;
    virtual int id() const { return 0; }
    virtual const char* rol() const { return "vizitator"; }
};

struct Utilizator : Cont {
    int id() const final { return 42; }
    const char* rol() const override { return "utilizator"; }
};

struct Admin final : Utilizator {
    const char* rol() const override { return "administrator"; }
};

int main() {
    Admin a;
    const Cont& c = a;
    std::println("id {}, rol {}", c.id(), c.rol());
    int final = 3;  // „final” poate fi și nume de variabilă
    std::println("final = {}", final);
}

Rezultat

id 42, rol administrator
final = 3

Greșeli frecvente

  • Nu folosești override și scrii void trimite(std::string text) const în derivată, când baza are const char*. Se creează o metodă nouă, iar apelurile prin bază ajung tot la varianta generică.
  • Pui override pe o metodă din bază care nu este virtual. Compilatorul refuză: doar metodele virtuale pot fi suprascrise.

Comenzi înrudite

  • virtual: Marchează o metodă care poate fi suprascrisă în clasele derivate; apelul printr-un pointer sau o referință la bază alege varianta tipului real.
  • class: Definește un tip nou care grupează date (membri) și funcțiile care lucrează cu ele (metode); baza programării orientate pe obiecte.
  • public, private, protected: Specificatorii de acces: stabilesc cine poate folosi membrii unei clase și cum se moștenește o clasă de bază.