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 scriivoid trimite(std::string text) constîn derivată, când baza areconst char*. Se creează o metodă nouă, iar apelurile prin bază ajung tot la varianta generică. - Pui
overridepe o metodă din bază care nu estevirtual. 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ă.