logo

Dziedziczenie w C++

Zdolność A klasa uzyskiwanie właściwości i cech charakterystycznych z innej klasy Dziedzictwo . Dziedziczenie jest jedną z najważniejszych cech programowania obiektowego.

Dziedziczenie to funkcja lub proces, w którym nowe klasy są tworzone z istniejących klas. Nowo utworzona klasa nazywana jest klasą pochodną lub klasą podrzędną, a istniejąca klasa nazywana jest klasą bazową lub klasą nadrzędną. Mówi się teraz, że klasa pochodna jest dziedziczona z klasy bazowej.



Kiedy mówimy, że klasa pochodna dziedziczy klasę bazową, oznacza to, że klasa pochodna dziedziczy wszystkie właściwości klasy bazowej, bez zmiany właściwości klasy bazowej i może dodawać nowe funkcje do swojej własnej. Te nowe funkcje w klasie pochodnej nie będą miały wpływu na klasę bazową. Klasa pochodna jest klasą wyspecjalizowaną dla klasy bazowej.

  • Podklasa: Klasa, która dziedziczy właściwości innej klasy, nazywa się podklasą lub klasą pochodną.
  • Super klasa: Klasa, której właściwości są dziedziczone przez podklasę, nazywana jest klasą bazową lub nadklasą.

Artykuł podzielony jest na następujące podtematy:

  • Dlaczego i kiedy stosować dziedziczenie?
  • Tryby dziedziczenia
  • Rodzaje dziedziczenia

Dlaczego i kiedy stosować dziedziczenie?

Rozważmy grupę pojazdów. Musisz utworzyć klasy dla autobusów, samochodów osobowych i ciężarówek. Metody FuelAmount(), pojemność(), ApplyBrakes() będą takie same dla wszystkich trzech klas. Jeśli utworzymy te klasy unikając dziedziczenia, będziemy musieli zapisać wszystkie te funkcje w każdej z trzech klas, jak pokazano na poniższym rysunku:



dziedziczenie w C++

wstawianie Pythona

Wyraźnie widać, że powyższy proces skutkuje 3-krotnym zduplikowaniem tego samego kodu. Zwiększa to ryzyko wystąpienia błędu i redundancji danych. Aby uniknąć tego typu sytuacji, stosuje się dziedziczenie. Jeśli utworzymy klasę Vehicle i zapiszemy w niej te trzy funkcje, a resztę klas odziedziczymy z klasy pojazdu, to możemy po prostu uniknąć duplikacji danych i zwiększyć ich ponowne wykorzystanie. Spójrz na poniższy diagram, na którym trzy klasy są dziedziczone z klasy pojazdu:

Aplikacja dziedziczenia w C++



Korzystając z dziedziczenia, musimy napisać funkcje tylko raz, a nie trzy razy, ponieważ pozostałe trzy klasy odziedziczyliśmy z klasy bazowej (Pojazd).
Implementacja dziedziczenia w C++ : Aby utworzyć podklasę dziedziczoną z klasy bazowej, musimy postępować zgodnie z poniższą składnią.

Klasy pochodne: Klasę pochodną definiuje się jako klasę pochodną klasy bazowej.
Składnia :

class :  {  //body }>

Gdzie
class — słowo kluczowe umożliwiające utworzenie nowej klasy
pochodna_klasa_nazwa — nazwa nowej klasy, która będzie dziedziczyć klasę bazową
specyfikator dostępu — prywatny, publiczny lub chroniony. Jeśli nie określono żadnego z nich, domyślnie przyjmuje się opcję PRIVATE
nazwa-klasy bazowej — nazwa klasy bazowej
Notatka : Klasa pochodna nie dziedziczy dostęp do prywatnych członków danych. Jednakże dziedziczy pełny obiekt nadrzędny, który zawiera wszystkie prywatne elementy członkowskie zadeklarowane przez tę klasę.

Przykład:
1. klasa ABC: prywatne XYZ //prywatne wyprowadzenie
{ }
2. klasa ABC: publiczne wyprowadzenie XYZ //publiczne
{ }
3. klasa ABC: chronione XYZ //chronione wyprowadzenie
{ }
4. klasa ABC: domyślnie XYZ //wyprowadzenie prywatne
{ }

Notatka:

o Kiedy klasa bazowa jest dziedziczona prywatnie przez klasę pochodną, ​​publiczne elementy klasy bazowej stają się prywatnymi członkami klasy pochodnej i dlatego dostęp do publicznych elementów klasy bazowej mogą uzyskać jedynie funkcje składowe klasy pochodnej. Są one niedostępne dla obiektów klasy pochodnej.
o Z drugiej strony, gdy klasa bazowa jest publicznie dziedziczona przez klasę pochodną, ​​publiczne elementy klasy bazowej stają się również publicznymi członkami klasy pochodnej. Dlatego publiczne składowe klasy bazowej są dostępne zarówno poprzez obiekty klasy pochodnej, jak i funkcje składowe klasy pochodnej.

C++
// Example: define member function without argument within // the class #include  using namespace std; class Person {  int id;  char name[100]; public:  void set_p()  {  cout << 'Enter the Id:';  cin>> identyfikator;  cout<< 'Enter the Name:';  cin>> imię;  } void display_p() { cout<< endl <<'Id: '<< id << '
Name: ' << name <> kurs;  cout<< 'Enter the Course Fee:';  cin>> opłata;  } void display_s() { display_p();  cout<<'Course: '<< course << '
Fee: ' << fee << endl;  } }; int main() {  Student s;  s.set_s();  s.display_s();  return 0; }>

Wyjście:

słuchaj portu
Enter the Id: 101 Enter the Name: Dev Enter the Course Name: GCS Enter the Course Fee:70000  Id: 101 Name: Dev Course: GCS Fee: 70000>
C++
// Example: define member function without argument outside the class #include using namespace std; class Person {  int id;  char name[100];    public:  void set_p();  void display_p(); }; void Person::set_p() {  cout<<'Enter the Id:';  cin>>identyfikator;  cout<<'Enter the Name:';  cin>> imię; } void Osoba::display_p() { cout<>oczywiście;  cout<<'Enter the Course Fee:';  cin>>opłata; } void Student::display_s() { display_p();  cout<<'
Course: '<

Wyjście:

Enter the Id: 101 Enter the Name: Dev Enter the Course Name: GCS Enter the Course Fee: 70000 Id: 101 Name: Dev Course: GCS Fee: 70000>
C++
// Example: define member function with argument outside the class #include #include using namespace std; class Person {  int id;  char name[100];    public:  void set_p(int,char[]);  void display_p(); }; void Person::set_p(int id,char n[]) {  this->identyfikator=identyfikator;  strcpy(this->name,n);  } void Osoba::display_p() { cout<

CPP
// C++ program to demonstrate implementation // of Inheritance #include  using namespace std; // Base class class Parent { public:  int id_p; }; // Sub class inheriting from Base Class(Parent) class Child : public Parent { public:  int id_c; }; // main function int main() {  Child obj1;  // An object of class child has all data members  // and member functions of class parent  obj1.id_c = 7;  obj1.id_p = 91;  cout << 'Child id is: ' << obj1.id_c << '
';  cout << 'Parent id is: ' << obj1.id_p << '
';  return 0; }>

Wyjście
Child id is: 7 Parent id is: 91>

W powyższym programie klasa „Child” jest publicznie dziedziczona z klasy „Parent”, więc publiczne elementy danych klasy „Parent” również zostaną odziedziczone przez klasę „Child”.
Tryby dziedziczenia: Istnieją 3 sposoby dziedziczenia.

  1. Tryb publiczny : Jeśli wyprowadzamy podklasę z publicznej klasy bazowej. Następnie publiczna składowa klasy bazowej stanie się publiczna w klasie pochodnej, a chronieni członkowie klasy bazowej staną się chronieni w klasie pochodnej.
  2. Tryb obronny : Jeśli wyprowadzamy podklasę z klasy bazowej Protected. Wtedy zarówno członkowie publiczni, jak i chronieni członkowie klasy bazowej staną się chronieni w klasie pochodnej.
  3. Tryb prywatny : Jeśli wyprowadzamy podklasę z klasy bazowej Private. Następnie zarówno członkowie publiczni, jak i chronieni członkowie klasy bazowej staną się prywatnymi w klasie pochodnej.

Notatka: Do prywatnych elementów klasy bazowej nie można uzyskać bezpośredniego dostępu w klasie pochodnej, można natomiast uzyskać bezpośredni dostęp do elementów chronionych. Na przykład klasy B, C i D zawierają zmienne x, y i z w poniższym przykładzie. To tylko kwestia dostępu.

CPP
// C++ Implementation to show that a derived class // doesn’t inherit access to private data members. // However, it does inherit a full parent object. class A { public:  int x; protected:  int y; private:  int z; }; class B : public A {  // x is public  // y is protected  // z is not accessible from B }; class C : protected A {  // x is protected  // y is protected  // z is not accessible from C }; class D : private A // 'private' is default for classes {  // x is private  // y is private  // z is not accessible from D };>


Poniższa tabela podsumowuje powyższe trzy tryby i przedstawia specyfikator dostępu elementów klasy bazowej w podklasie, gdy jest wyprowadzany w trybach publicznym, chronionym i prywatnym:

Rodzaje dziedziczenia: -

  1. Pojedyncze dziedzictwo
  2. Dziedziczenie wielopoziomowe
  3. Dziedziczenie wielokrotne
  4. Dziedziczenie hierarchiczne
  5. Dziedziczenie hybrydowe

Rodzaje dziedziczenia w C++

1. Pojedyncze dziedzictwo : W przypadku dziedziczenia pojedynczego klasa może dziedziczyć tylko z jednej klasy. tj. jedna podklasa jest dziedziczona tylko przez jedną klasę bazową.

Pojedyncze dziedziczenie w C++

Składnia :

class subclass_name : access_mode base_class {  // body of subclass }; OR class A {  ... .. ...  }; class B: public A { ... .. ... };>
CPP
// C++ program to explain  // Single inheritance #include using namespace std; // base class class Vehicle {  public:  Vehicle()  {  cout << 'This is a Vehicle
';  } }; // sub class derived from a single base classes class Car : public Vehicle { }; // main function int main() {   // Creating object of sub class will  // invoke the constructor of base classes  Car obj;  return 0; }>

Wyjście
This is a Vehicle>

C++
// Example: #include using namespace std; class A {  protected:  int a;    public:  void set_A()  {  cout<<'Enter the Value of A=';  cin>>a;    } void disp_A() { cout<Wynik:- Wprowadź wartość A= 3 3 Wprowadź wartość B= 5 5 Iloczyn 3 * 5 = 15

C++
// Example: #include using namespace std; class A {  protected:  int a;    public:  void set_A(int x)  {  a=x;   }    void disp_A()  {  cout<Product of 4 * 5 = 20>

2. Dziedziczenie wielokrotne: Dziedziczenie wielokrotne to funkcja języka C++, dzięki której klasa może dziedziczyć z więcej niż jednej klasy. tj. jeden podklasa jest dziedziczony od więcej niż jednego klasa bazowa .

Dziedziczenie wielokrotne w C++

Składnia :

class subclass_name : access_mode base_class1, access_mode base_class2, .... {  // body of subclass }; class B {  ... .. ...  }; class C { ... .. ... }; class A: public B, public C { ... ... ... };>

Tutaj liczba klas bazowych zostanie oddzielona przecinkiem („,”) i należy określić tryb dostępu dla każdej klasy bazowej.

CPP
// C++ program to explain // multiple inheritance #include  using namespace std; // first base class class Vehicle { public:  Vehicle() { cout << 'This is a Vehicle
'; } }; // second base class class FourWheeler { public:  FourWheeler()  {  cout << 'This is a 4 wheeler Vehicle
';  } }; // sub class derived from two base classes class Car : public Vehicle, public FourWheeler { }; // main function int main() {  // Creating object of sub class will  // invoke the constructor of base classes.  Car obj;  return 0; }>

Wyjście
This is a Vehicle This is a 4 wheeler Vehicle>

C++
// Example: #include using namespace std; class A {  protected:  int a;    public:  void set_A()  {  cout<<'Enter the Value of A=';  cin>>a;    } void disp_A() { cout<Aby dowiedzieć się więcej na ten temat, zapoznaj się z artykułem Wiele spadków .


3. Dziedziczenie wielopoziomowe : W przypadku tego typu dziedziczenia klasa pochodna jest tworzona na podstawie innej klasy pochodnej.

Dziedziczenie wielopoziomowe w C++

urodził się Freddie Mercury

Składnia:-

class C {  ... .. ...  }; class B:public C { ... .. ... }; class A: public B { ... ... ... };>
CPP
// C++ program to implement // Multilevel Inheritance #include  using namespace std; // base class class Vehicle { public:  Vehicle() { cout << 'This is a Vehicle
'; } }; // first sub_class derived from class vehicle class fourWheeler : public Vehicle { public:  fourWheeler()  {  cout << 'Objects with 4 wheels are vehicles
';  } }; // sub class derived from the derived base class fourWheeler class Car : public fourWheeler { public:  Car() { cout << 'Car has 4 Wheels
'; } }; // main function int main() {  // Creating object of sub class will  // invoke the constructor of base classes.  Car obj;  return 0; }>

Wyjście
This is a Vehicle Objects with 4 wheels are vehicles Car has 4 Wheels>

4. Dziedziczenie hierarchiczne : W tego typu dziedziczeniu więcej niż jedna podklasa jest dziedziczona z jednej klasy bazowej. tj. z jednej klasy bazowej tworzona jest więcej niż jedna klasa pochodna.

Dziedziczenie hierarchiczne w C++

polecenie arp-a

Składnia:-

class A  {   // body of the class A.  }  class B : public A  {   // body of class B.  }  class C : public A  {   // body of class C.  }  class D : public A  {   // body of class D.  }>
CPP
// C++ program to implement // Hierarchical Inheritance #include  using namespace std; // base class class Vehicle { public:  Vehicle() { cout << 'This is a Vehicle
'; } }; // first sub class class Car : public Vehicle { }; // second sub class class Bus : public Vehicle { }; // main function int main() {  // Creating object of sub class will  // invoke the constructor of base class.  Car obj1;  Bus obj2;  return 0; }>

Wyjście
This is a Vehicle This is a Vehicle>

5. Dziedziczenie hybrydowe (wirtualne). : Dziedziczenie hybrydowe jest realizowane poprzez połączenie więcej niż jednego rodzaju dziedziczenia. Na przykład: połączenie dziedziczenia hierarchicznego i dziedziczenia wielokrotnego.
Poniższy obrazek przedstawia kombinację dziedziczenia hierarchicznego i wielokrotnego:

Dziedziczenie hybrydowe w C++.

CPP
// C++ program for Hybrid Inheritance #include  using namespace std; // base class class Vehicle { public:  Vehicle() { cout << 'This is a Vehicle
'; } }; // base class class Fare { public:  Fare() { cout << 'Fare of Vehicle
'; } }; // first sub class class Car : public Vehicle { }; // second sub class class Bus : public Vehicle, public Fare { }; // main function int main() {  // Creating object of sub class will  // invoke the constructor of base class.  Bus obj2;  return 0; }>

Wyjście
This is a Vehicle Fare of Vehicle>
C++
// Example: #include   using namespace std;  class A  {   protected:   int a;   public:   void get_a()   {   cout << 'Enter the value of 'a' : ';   cin>>a;   } };    klasa B: publiczna A {chroniona: int b;   public: void get_b() { cout<< 'Enter the value of 'b' : ';  cin>>b;   } };  klasa C {chroniona: int c;   public: void get_c() { cout<< 'Enter the value of c is : ';   cin>>c;   } };    klasa D: publiczna B, publiczna C {chroniona: int d;   public: void mul() { get_a();   get_b();   get_c();   cout<< 'Multiplication of a,b,c is : ' < 

6. Szczególny przypadek dziedziczenia hybrydowego: dziedziczenie wielościeżkowe :
Klasa pochodna z dwiema klasami bazowymi i te dwie klasy bazowe mają jedną wspólną klasę bazową, nazywana jest dziedziczeniem wielościeżkowym. W tego typu dziedziczeniu mogą pojawić się niejasności.
Przykład:

CPP
// C++ program demonstrating ambiguity in Multipath // Inheritance #include  using namespace std; class ClassA { public:  int a; }; class ClassB : public ClassA { public:  int b; }; class ClassC : public ClassA { public:  int c; }; class ClassD : public ClassB, public ClassC { public:  int d; }; int main() {  ClassD obj;  // obj.a = 10; // Statement 1, Error  // obj.a = 100; // Statement 2, Error  obj.ClassB::a = 10; // Statement 3  obj.ClassC::a = 100; // Statement 4  obj.b = 20;  obj.c = 30;  obj.d = 40;  cout << ' a from ClassB : ' << obj.ClassB::a;  cout << '
 a from ClassC : ' << obj.ClassC::a;  cout << '
 b : ' << obj.b;  cout << '
 c : ' << obj.c;  cout << '
 d : ' << obj.d << '
'; }>

Wyjście
 a from ClassB : 10 a from ClassC : 100 b : 20 c : 30 d : 40>

W powyższym przykładzie zarówno klasa B, jak i klasa C dziedziczą klasę A, obie mają jedną kopię klasy A. Jednakże klasa D dziedziczy zarówno klasę B, jak i klasę C, dlatego klasa D ma dwie kopie klasy A, jedną z klasy B i drugą z klasy C.
Jeśli potrzebujemy uzyskać dostęp do elementu danych ClassA poprzez obiekt klasy D, musimy określić ścieżkę, z której będzie uzyskiwany dostęp do a, niezależnie od tego, czy będzie to klasa B, czy ClassC, ponieważ kompilator nie może rozróżnić dwóch kopii ClassA w Klasa D.

Istnieją 2 sposoby uniknięcia tej dwuznaczności:

1) Unikanie niejednoznaczności za pomocą operatora rozdzielczości zakresu: Używając operatora rozpoznawania zakresu, możemy ręcznie określić ścieżkę, z której będzie uzyskiwany dostęp do elementu danych a, jak pokazano w instrukcjach 3 i 4 w powyższym przykładzie.

CPP
obj.ClassB::a = 10; // Statement 3 obj.ClassC::a = 100; // Statement 4>


Notatka: Mimo to w klasie D znajdują się dwie kopie klasy A.
2) Unikanie dwuznaczności przy użyciu wirtualnej klasy bazowej:

CPP
#include class ClassA {  public:  int a; }; class ClassB : virtual public ClassA {  public:  int b; }; class ClassC : virtual public ClassA {  public:  int c; }; class ClassD : public ClassB, public ClassC {  public:  int d; }; int main() {  ClassD obj;  obj.a = 10; // Statement 3  obj.a = 100; // Statement 4  obj.b = 20;  obj.c = 30;  obj.d = 40;  cout << '
 a : ' << obj.a;  cout << '
 b : ' << obj.b;  cout << '
 c : ' << obj.c;  cout << '
 d : ' << obj.d << '
'; }>

Wyjście:

a : 100 b : 20 c : 30 d : 40>

Zgodnie z powyższym przykładem klasa D ma tylko jedną kopię klasy A, zatem instrukcja 4 nadpisze wartość a podaną w instrukcji 3.