Dziedziczenie w C++
Dziedziczenie jest podstawową koncepcją w OOP (programowanie obiektowe) . Jest to mechanizm, dzięki któremu jedna klasa może dziedziczyć cechy (pola i metody) innej klasy. Dziedziczenie oznacza tworzenie nowych klas w oparciu o już istniejące. Klasa dziedzicząca z innej klasy może ponownie wykorzystać metody i pola tej klasy.
Przykład: W poniższym przykładzie Animal jest klasą bazową, a Dog Cat i Cow są klasami pochodnymi, które rozszerzają klasę 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 ; }
Wyjście
Dog barks Cat meows Cow moos
Wyjaśnienie:
- Animal jest klasą bazową z funkcją sound().
- Dog Cat i Cow to klasy pochodne, z których każda definiuje własną metodę sound().
- W funkcji main() obiekty Dog Cat i Cow są tworzone oddzielnie.
- Kiedy wywołujemy funkcję sound() na każdym obiekcie, uruchamiana jest odpowiednia metoda klasy potomnej (Pies szczeka Kot miauczy Krowa muczy).
Składnia
C++ class ChildClass : public ParentClass { // Additional fields and methods };
Jak działa dziedziczenie w C++?
Dwukropek (:) z specyfikator dostępu służy do dziedziczenia w C++. Pozwala klasie pochodnej (klasie podrzędnej) dziedziczyć elementy danych (pola) i funkcje składowe (metody) klasy bazowej (klasy nadrzędnej).
Kiedy klasa dziedziczy inną klasę, otrzymuje wszystkich dostępnych członków klasy nadrzędnej, a klasa podrzędna może również przedefiniować (przesłonić) lub dodać do nich nową funkcjonalność.
Rodzaje dziedziczenia w C++
Poniżej znajdują się różne typy dziedziczenia obsługiwane przez C++.
1. Pojedyncze dziedzictwo
W przypadku pojedynczego dziedziczenia podklasa pochodzi tylko z jednej nadklasy. Dziedziczy właściwości i zachowanie klasy z jednym rodzicem. Czasami nazywa się to również prostym dziedziczeniem.
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 ; }
Wyjście
This is a Vehicle This Vehicle is Car
2. Dziedziczenie wielokrotne
W Dziedziczenie wielokrotne jedna klasa może mieć więcej niż jedną nadklasę i dziedziczyć funkcje ze wszystkich klas nadrzędnych.
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 ; }
Wyjście
This is an AmphibiousVehicle This is a WaterVehicle This is a LandVehicle
3. Dziedziczenie wielopoziomowe
Dziedziczenie wielopoziomowe w C++ oznacza, że klasa wywodzi się z innej klasy pochodnej tworzącej łańcuch dziedziczenia.
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 ; }
Wyjście
This is a Vehicle 4 Wheeler Vehicles This 4 Wheeler Vehicle is a Car
4. Dziedziczenie hierarchiczne
W dziedziczeniu hierarchicznym więcej niż jedna podklasa jest dziedziczona z jednej klasy bazowej. tj. z jednej klasy bazowej tworzona jest więcej niż jedna klasa pochodna. Na przykład samochody i autobusy są pojazdami.
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 ; }
Wyjście
This is a Vehicle This Vehicle is Car This is a Vehicle This Vehicle is Bus
5. Dziedziczenie hybrydowe
Gdy dwa lub więcej typów dziedziczenia są połączone w jednym programie. Na przykład klasa może korzystać z dziedziczenia wielokrotnego i być częścią wielopoziomowego łańcucha dziedziczenia.
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 ; }
Wyjście
This is a Vehicle Fare of Vehicle This Vehicle is a Bus with Fare
Dziedziczenie hybrydowe może prowadzić do problem diamentów w C++. Dzieje się tak, gdy klasa dziedziczy po dwóch klasach, które korzystają z tej samej klasy bazowej. W rezultacie klasa pochodna otrzymuje wiele kopii elementów klasy bazowej, co powoduje niejasność co do tego, którego z nich użyć.
Notatka : Rozwiązaniem jest użycie dziedziczenia wirtualnego, tak aby współużytkowana była tylko jedna kopia klasy bazowej.
Zalety dziedziczenia w C++
- Możliwość ponownego wykorzystania kodu : Klasa pochodna może bezpośrednio ponownie wykorzystywać elementy danych i metody swojej klasy bazowej, unikając duplikacji kodu.
- Abstrakcja: Obsługuje klasy abstrakcyjne (klasy z funkcjami czysto wirtualnymi), które definiują wspólny interfejs wymuszający abstrakcję.
- Hierarchia klas: Można budować hierarchie (podstawowe → pochodne → dalsze pochodne), aby modelować relacje w świecie rzeczywistym.
- Polimorfizm: W pełni obsługuje polimorfizm w czasie wykonywania poprzez funkcje wirtualne, a także polimorfizm w czasie kompilacji poprzez przeciążanie funkcji i szablony.
Wady dziedziczenia w C++
- Ciasne sprzęgło: Klasa potomna staje się zależna od klasy nadrzędnej. Jakakolwiek zmiana w klasie bazowej może wymusić zmiany w klasach pochodnych.
- Zmniejszona elastyczność: Czasami dziedziczenie jest niewłaściwie wykorzystywane, gdy kompozycja (relacja ma) byłaby lepsza, co prowadziłoby do mniej elastycznego kodu.
- Zwiększona złożoność: Głębokie hierarchie dziedziczenia (wielopoziomowe lub hybrydowe) mogą sprawić, że kod będzie trudny do zrozumienia w utrzymaniu i debugowaniu.
- Problem z diamentem: W przypadku dziedziczenia hybrydowego lub wielokrotnego dziedziczenia może wystąpić niejednoznaczność, jeśli ta sama klasa bazowa jest dziedziczona wielokrotnie.
- Narzut funkcji wirtualnych: Jeśli używany jest polimorfizm (funkcje wirtualne), narzut w czasie wykonywania jest niewielki ze względu na przeglądanie tabel wirtualnych.