logo

Herencia en C++

La capacidad de un clase derivar propiedades y características de otra clase se llama Herencia . La herencia es una de las características más importantes de la programación orientada a objetos.

La herencia es una característica o un proceso en el que se crean nuevas clases a partir de las clases existentes. La nueva clase creada se llama clase derivada o clase secundaria y la clase existente se conoce como clase base o clase principal. Ahora se dice que la clase derivada se hereda de la clase base.



Cuando decimos que la clase derivada hereda la clase base, significa que la clase derivada hereda todas las propiedades de la clase base, sin cambiar las propiedades de la clase base y puede agregar nuevas características a las suyas. Estas nuevas características en la clase derivada no afectarán a la clase base. La clase derivada es la clase especializada de la clase base.

  • Subclase: La clase que hereda propiedades de otra clase se llama Subclase o Clase Derivada.
  • Superclase: La clase cuyas propiedades son heredadas por una subclase se llama Clase Base o Superclase.

El artículo se divide en los siguientes subtemas:

  • ¿Por qué y cuándo utilizar la herencia?
  • Modos de herencia
  • Tipos de herencia

¿Por qué y cuándo utilizar la herencia?

Considere un grupo de vehículos. Necesita crear clases para autobús, automóvil y camión. Los métodos fuelAmount(), capacidad(), applyBrakes() serán los mismos para las tres clases. Si creamos estas clases evitando la herencia, entonces tenemos que escribir todas estas funciones en cada una de las tres clases como se muestra a continuación en la figura:



herencia en C++

prueba la estructura de datos

Puede ver claramente que el proceso anterior da como resultado la duplicación del mismo código 3 veces. Esto aumenta las posibilidades de error y redundancia de datos. Para evitar este tipo de situaciones se utiliza la herencia. Si creamos una clase Vehículo y escribimos estas tres funciones en ella y heredamos el resto de las clases de la clase de vehículo, entonces simplemente podemos evitar la duplicación de datos y aumentar la reutilización. Mire el siguiente diagrama en el que las tres clases se heredan de la clase de vehículo:

aplicación de herencia en C++



Al usar la herencia, tenemos que escribir las funciones solo una vez en lugar de tres, ya que hemos heredado el resto de las tres clases de la clase base (Vehículo).
Implementando herencia en C++ : Para crear una subclase heredada de la clase base, debemos seguir la siguiente sintaxis.

Clases derivadas: Una clase derivada se define como la clase derivada de la clase base.
Sintaxis :

class :  {  //body }>

Dónde
clase: palabra clave para crear una nueva clase
derive_class_name — nombre de la nueva clase, que heredará la clase base
especificador de acceso: ya sea privado, público o protegido. Si no se especifica ninguno, se toma PRIVADO como predeterminado
nombre-clase-base: nombre de la clase base
Nota : una clase derivada no hereda acceso a miembros de datos privados. Sin embargo, hereda un objeto principal completo, que contiene los miembros privados que declara esa clase.

Ejemplo:
1. clase ABC: XYZ privado //derivación privada
{ }
2. clase ABC: público XYZ //derivación pública
{ }
3. clase ABC: XYZ protegido //derivación protegida
{ }
4. clase ABC: XYZ //derivación privada por defecto
{ }

Nota:

o Cuando una clase base es heredada de forma privada por la clase derivada, los miembros públicos de la clase base se convierten en miembros privados de la clase derivada y, por lo tanto, solo las funciones miembro de la clase derivada pueden acceder a los miembros públicos de la clase base. Son inaccesibles para los objetos de la clase derivada.
o Por otro lado, cuando la clase derivada hereda públicamente la clase base, los miembros públicos de la clase base también se convierten en miembros públicos de la clase derivada. Por lo tanto, los miembros públicos de la clase base son accesibles tanto por los objetos de la clase derivada como por las funciones miembro de la clase derivada.

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>> identificación;  corte<< 'Enter the Name:';  cin>> nombre;  } void display_p() { cout<< endl <<'Id: '<< id << '
Name: ' << name <> curso;  corte<< 'Enter the Course Fee:';  cin>> tarifa;  } void display_s() { display_p();  corte<<'Course: '<< course << '
Fee: ' << fee << endl;  } }; int main() {  Student s;  s.set_s();  s.display_s();  return 0; }>

Producción:

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>>identificación;  corte<<'Enter the Name:';  cin>>nombre; } persona vacía::display_p() { cout<>curso;  corte<<'Enter the Course Fee:';  cin>>tarifa; } void Estudiante::display_s() { display_p();  corte<<'
Course: '<

Producción:

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->identificación=identificación;  strcpy(este->nombre,n);  } persona vacía::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; }>

Producción
Child id is: 7 Parent id is: 91>

En el programa anterior, la clase 'Hijo' se hereda públicamente de la clase 'Padre', por lo que los datos públicos de los miembros de la clase 'Padre' también serán heredados por la clase 'Hijo'.
Modos de herencia: Hay 3 modos de herencia.

centos vs sombrero rojo
  1. Modo público : Si derivamos una subclase de una clase base pública. Luego, el miembro público de la clase base pasará a ser público en la clase derivada y los miembros protegidos de la clase base pasarán a estar protegidos en la clase derivada.
  2. Modo protegido : Si derivamos una subclase de una clase base protegida. Entonces, tanto los miembros públicos como los miembros protegidos de la clase base quedarán protegidos en la clase derivada.
  3. Modo privado : Si derivamos una subclase de una clase base privada. Entonces, tanto los miembros públicos como los miembros protegidos de la clase base se convertirán en privados en la clase derivada.

Nota: No se puede acceder directamente a los miembros privados de la clase base en la clase derivada, mientras que se puede acceder directamente a los miembros protegidos. Por ejemplo, las clases B, C y D contienen las variables x, y y z en el siguiente ejemplo. Es sólo una cuestión de acceso.

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 };>


La siguiente tabla resume los tres modos anteriores y muestra el especificador de acceso de los miembros de la clase base en la subclase cuando se deriva en los modos público, protegido y privado:

Tipos de herencia: -

  1. herencia única
  2. Herencia multinivel
  3. herencia múltiple
  4. Herencia jerárquica
  5. Herencia híbrida

Tipos de herencia en C++

1. Herencia única : En herencia única, una clase puede heredar de una sola clase. es decir, una subclase es heredada solo por una clase base.

Herencia única en C++

Sintaxis :

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; }>

Producción
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>>un;    } vacío disp_A() { cout<Salida:- Ingrese el valor de A= 3 3 Ingrese el valor de B= 5 5 Producto de 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. Herencia múltiple: La herencia múltiple es una característica de C++ donde una clase puede heredar de más de una clase. es decir uno subclase se hereda de más de uno clase base .

Herencia múltiple en C++

Sintaxis :

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

Aquí, el número de clases base estará separado por una coma (', ') y se debe especificar el modo de acceso para cada clase base.

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; }>

Producción
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>>un;    } vacío disp_A() { cout<Para saber más al respecto, consulte el artículo. Herencias Múltiples .


3. Herencia multinivel : En este tipo de herencia, una clase derivada se crea a partir de otra clase derivada.

Herencia multinivel en C++

freddie mercurio nacido

Sintaxis:-

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; }>

Producción
This is a Vehicle Objects with 4 wheels are vehicles Car has 4 Wheels>

4. Herencia jerárquica : En este tipo de herencia, se hereda más de una subclase de una única clase base. es decir, se crea más de una clase derivada a partir de una única clase base.

Herencia jerárquica en C++

Sintaxis:-

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; }>

Producción
This is a Vehicle This is a Vehicle>

5. Herencia híbrida (virtual) : La herencia híbrida se implementa combinando más de un tipo de herencia. Por ejemplo: Combinando herencia jerárquica y herencia múltiple.
La siguiente imagen muestra la combinación de herencias jerárquicas y múltiples:

Herencia híbrida en 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; }>

Producción
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>>un;   } };    clase B: público A { protegido: int b;   público: void get_b() { cout<< 'Enter the value of 'b' : ';  cin>>b;   } };  clase C {protegido: int c;   público: void get_c() { cout<< 'Enter the value of c is : ';   cin>>c;   } };    clase D: público B, público C {protegido: int d;   público: void mul() { get_a();   get_b();   get_c();   corte<< 'Multiplication of a,b,c is : ' < 

6. Un caso especial de herencia híbrida: herencia por trayectos múltiples :
Una clase derivada con dos clases base y estas dos clases base tienen una clase base común se denomina herencia de rutas múltiples. En este tipo de herencia puede surgir ambigüedad.
Ejemplo:

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 << '
'; }>

Producción
 a from ClassB : 10 a from ClassC : 100 b : 20 c : 30 d : 40>

En el ejemplo anterior, tanto ClassB como ClassC heredan ClassA, ambos tienen una única copia de ClassA. Sin embargo, la Clase D hereda tanto la Clase B como la Clase C, por lo tanto, la Clase D tiene dos copias de la Clase A, una de la Clase B y otra de la Clase C.
Si necesitamos acceder al miembro de datos de ClassA a través del objeto de Class-D, debemos especificar la ruta desde la cual se accederá a, ya sea desde ClassB o ClassC, el compilador bcoz no puede diferenciar entre dos copias de ClassA en Clase D.

Hay 2 formas de evitar esta ambigüedad:

1) Evitar ambigüedades utilizando el operador de resolución de alcance: Usando el operador de resolución de alcance podemos especificar manualmente la ruta desde la cual se accederá al miembro de datos a, como se muestra en las declaraciones 3 y 4, en el ejemplo anterior.

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


Nota: Aún así, hay dos copias de ClassA en Class-D.
2) Evitar la ambigüedad utilizando la clase base virtual:

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 << '
'; }>

Producción:

procesamiento de piratería
a : 100 b : 20 c : 30 d : 40>

Según el ejemplo anterior, la Clase D tiene solo una copia de la Clase A, por lo tanto, la declaración 4 sobrescribirá el valor de a, dado en la declaración 3.