Ereditarietà in C++
L'ereditarietà è un concetto fondamentale in OOP (programmazione orientata agli oggetti) . È il meccanismo mediante il quale una classe può ereditare le funzionalità (campi e metodi) di un'altra classe. Ereditarietà significa creare nuove classi basate su quelle esistenti. Una classe che eredita da un'altra classe può riutilizzare i metodi e i campi di quella classe.
Esempio: Nell'esempio seguente Animal è la classe base e Dog Cat e Cow sono classi derivate che estendono la classe Animal.
Inheritance C++ #include using namespace std ; class Animal { public : void sound () { cout < < 'Animal makes a sound' < < endl ; } }; class Dog : public Animal { public : void sound () { cout < < 'Dog barks' < < endl ; } }; class Cat : public Animal { public : void sound () { cout < < 'Cat meows' < < endl ; } }; class Cow : public Animal { public : void sound () { cout < < 'Cow moos' < < endl ; } }; int main () { Dog d ; d . sound (); Cat c ; c . sound (); Cow cow ; cow . sound (); return 0 ; }
Produzione
Dog barks Cat meows Cow moos
Spiegazione:
- Animal è la classe base con una funzione sound().
- Dog Cat e Cow sono classi derivate, ciascuna delle quali definisce il proprio metodo sound().
- In main() gli oggetti Cane Gatto e Mucca vengono creati separatamente.
- Quando chiamiamo sound() su ciascun oggetto viene eseguito il rispettivo metodo della classe figlia (Il cane abbaia Il gatto miagola La mucca muggisce).
Sintassi
C++ class ChildClass : public ParentClass { // Additional fields and methods };
Come funziona l'ereditarietà in C++?
I due punti (:) con un specificatore di accesso viene utilizzato per l'ereditarietà in C++. Consente alla classe derivata (classe figlia) di ereditare i membri dati (campi) e le funzioni membro (metodi) della classe base (classe genitore).
Quando una classe eredita un'altra classe, ottiene tutti i membri accessibili della classe genitore e la classe figlia può anche ridefinirli (sovrascriverli) o aggiungere loro nuove funzionalità.
Tipi di ereditarietà in C++
Di seguito sono riportati i diversi tipi di ereditarietà supportati da C++.
1. Eredità unica
Nell'ereditarietà singola una sottoclasse deriva da una sola superclasse. Eredita le proprietà e il comportamento di una classe a genitore singolo. A volte è conosciuta anche come eredità semplice.
Single Inheritance C++ #include using namespace std ; class Vehicle { public : Vehicle () { cout < < 'This is a Vehicle' < < endl ; } }; class Car : public Vehicle { public : Car () { cout < < 'This Vehicle is Car' < < endl ; } }; int main () { Car obj ; return 0 ; }
Produzione
This is a Vehicle This Vehicle is Car
2. Eredità multipla
In Eredità multipla una classe può avere più di una superclasse ed ereditare funzionalità da tutte le classi genitori.
Multiple Inheritance C++ #include using namespace std ; class LandVehicle { public : void landInfo () { cout < < 'This is a LandVehicle' < < endl ; } }; class WaterVehicle { public : void waterInfo () { cout < < 'This is a WaterVehicle' < < endl ; } }; // Derived class inheriting from both base classes class AmphibiousVehicle : public LandVehicle public WaterVehicle { public : AmphibiousVehicle () { cout < < 'This is an AmphibiousVehicle' < < endl ; } }; int main () { AmphibiousVehicle obj ; obj . waterInfo (); obj . landInfo (); return 0 ; }
Produzione
This is an AmphibiousVehicle This is a WaterVehicle This is a LandVehicle
3. Eredità multilivello
L'ereditarietà multilivello in C++ significa che una classe deriva da un'altra classe derivata che forma una catena di ereditarietà.
Multilevel Inheritance C++ #include using namespace std ; class Vehicle { public : Vehicle () { cout < < 'This is a Vehicle' < < endl ; } }; // Derived class from Vehicle class FourWheeler : public Vehicle { public : FourWheeler () { cout < < '4 Wheeler Vehicles' < < endl ; } }; // Derived class from FourWheeler class Car : public FourWheeler { public : Car () { cout < < 'This 4 Wheeler Vehicle is a Car' < < endl ; } }; int main () { Car obj ; return 0 ; }
Produzione
This is a Vehicle 4 Wheeler Vehicles This 4 Wheeler Vehicle is a Car
4. Eredità gerarchica
Nell'ereditarietà gerarchica più di una sottoclasse viene ereditata da una singola classe base. cioè più di una classe derivata viene creata da una singola classe base. Ad esempio, le automobili e gli autobus sono entrambi veicoli.
Hierarchical Inheritance C++ #include using namespace std ; class Vehicle { public : Vehicle () { cout < < 'This is a Vehicle' < < endl ; } }; class Car : public Vehicle { public : Car () { cout < < 'This Vehicle is Car' < < endl ; } }; class Bus : public Vehicle { public : Bus () { cout < < 'This Vehicle is Bus' < < endl ; } }; int main () { Car obj1 ; Bus obj2 ; return 0 ; }
Produzione
This is a Vehicle This Vehicle is Car This is a Vehicle This Vehicle is Bus
5. Eredità ibrida
Quando due o più tipi di ereditarietà sono combinati in un unico programma. Ad esempio, una classe potrebbe utilizzare l'ereditarietà multipla e anche far parte di una catena di ereditarietà multilivello.
Hybrid Inheritance C++ #include using namespace std ; class Vehicle { public : Vehicle () { cout < < 'This is a Vehicle' < < endl ; } }; class Fare { public : Fare () { cout < < 'Fare of Vehicle' < < endl ; } }; class Car : public Vehicle { public : Car () { cout < < 'This Vehical is a Car' < < endl ; } }; class Bus : public Vehicle public Fare { public : Bus () { cout < < 'This Vehicle is a Bus with Fare' ; } }; int main () { Bus obj2 ; return 0 ; }
Produzione
This is a Vehicle Fare of Vehicle This Vehicle is a Bus with Fare
L'ereditarietà ibrida può portare a problema dei diamanti nel C++. Ciò accade quando una classe eredita da due classi che condividono entrambe la stessa classe base. Di conseguenza, la classe derivata ottiene più copie dei membri della classe base, il che crea ambiguità su quale utilizzare.
Nota: La soluzione è utilizzare l'ereditarietà virtuale in modo che venga condivisa solo una singola copia della classe base.
Vantaggi dell'ereditarietà in C++
- Riutilizzabilità del codice : La classe derivata può riutilizzare direttamente i membri dati e i metodi della sua classe base evitando la duplicazione del codice.
- Astrazione: Supporta classi astratte (classi con funzioni virtuali pure) che definiscono un'interfaccia comune che impone l'astrazione.
- Gerarchia delle classi: È possibile creare gerarchie (base → derivato → ulteriormente derivato) per modellare le relazioni del mondo reale.
- Polimorfismo: Supporta completamente il polimorfismo in fase di esecuzione tramite funzioni virtuali e anche il polimorfismo in fase di compilazione tramite sovraccarico delle funzioni e modelli.
Svantaggi dell'ereditarietà in C++
- Accoppiamento stretto: La classe figlia diventa dipendente dalla classe genitore. Qualsiasi modifica nella classe base può forzare modifiche nelle classi derivate.
- Flessibilità ridotta: A volte l'ereditarietà viene utilizzata in modo improprio laddove la composizione (relazione has-a) sarebbe migliore portando a un codice meno flessibile.
- Maggiore complessità: Gerarchie di ereditarietà profonde (multilivello o ibride) possono rendere difficile la comprensione, la manutenzione e il debug del codice.
- Problema del diamante: Con l'ereditarietà ibrida o multipla può verificarsi ambiguità se la stessa classe base viene ereditata più volte.
- Sovraccarico delle funzioni virtuali: Se viene utilizzato il polimorfismo (funzioni virtuali), c'è un piccolo sovraccarico di runtime dovuto alle ricerche nelle tabelle virtuali.