Herencia de subclase de C++

Namita Chaudhary 12 octubre 2023
  1. Herencia de subclase de C++
  2. Herencia múltiple en subclase en C++
  3. Herencia jerárquica en subclase en C++
  4. El problema del diamante en la herencia en C++
  5. Conclusión
Herencia de subclase de C++

La herencia es una característica de OOP en la que una clase adquiere las propiedades y el comportamiento de otra clase. Una clase que hereda otra clase se llama subclase, mientras que la clase cuyas propiedades se heredan se conoce como clase base.

Este artículo discutirá el problema del diamante que ocurre al heredar las clases.

Herencia de subclase de C++

La herencia es una característica que permite que una clase herede las propiedades de otra clase. La clase que hereda las propiedades de otra clase se conoce como subclase o clase derivada, mientras que la clase cuyas propiedades se heredan se conoce como clase base o clase padre.

Un ejemplo real de herencia puede ser un niño que hereda las propiedades de sus padres.

Hay principalmente cinco tipos de herencia en C++, a saber, herencia única, herencia múltiple, herencia multinivel, herencia jerárquica y herencia híbrida.

  1. Herencia única: en este tipo de herencia, una sola subclase hereda de una sola clase base.
  2. Herencia múltiple: en este tipo de herencia, la subclase se hereda de más de una clase base.
  3. Herencia jerárquica: en este tipo de herencia, se heredan varias subclases de la misma clase base.
  4. Herencia multinivel: en este tipo de herencia, una clase es heredada por otra clase que, a su vez, también es heredada por otra clase. Por ejemplo, tenemos tres clases, A, B y C, en las que la clase C la hereda la clase B y la clase B la hereda la clase A.
  5. Herencia híbrida: en este tipo de herencia, se combinan más de un tipo de herencia.

Primero hablaremos sobre la herencia múltiple y jerárquica en C++.

Herencia múltiple en subclase en C++

Como se describió anteriormente, una subclase es heredada por varias otras clases base en herencias múltiples. Tomemos un ejemplo para entender la herencia múltiple en detalle.

#include <iostream>
using namespace std;
class Base1 {
 public:
  Base1() { cout << "Base class 1" << endl; }
};

class Base2 {
 public:
  Base2() { cout << "Base class 2" << endl; }
};

class Derived : public Base2, public Base1 {
 public:
  Derived() { cout << "Derived class" << endl; }
};

int main() {
  Derived d;
  return 0;
}

Producción :

Base class 2
Base class 1
Derived class

El código anterior tiene dos clases base, Base1 y Base2, de las que se hereda la clase Derivado. Sin embargo, debe tener en cuenta el orden en que se llama a los constructores de las clases base.

Primero se llama al constructor de la clase Base2 porque primero lo hereda la clase Derivado y luego el constructor Base1.

Herencia jerárquica en subclase en C++

Como se describió anteriormente, varias subclases se heredan de una sola clase base en la herencia jerárquica. Tomemos un ejemplo para entender la herencia jerárquica en detalle.

#include <iostream>
using namespace std;
class Base {
 public:
  Base() { cout << "Base class" << endl; }
};

class Derived1 : public Base {
 public:
  Derived1() { cout << "Derived class 1" << endl; }
};

class Derived2 : public Base {
 public:
  Derived2() { cout << "Derived class 2" << endl; }
};

int main() {
  Derived1 d1;
  Derived2 d2;
  return 0;
}

Producción :

Base class
Derived class 1
Base class
Derived class 2

El ejemplo de código anterior tiene tres clases en las que las clases Derived1 y Derived2 se heredan de la clase común Base.

El problema del diamante en la herencia en C++

El problema del diamante ocurre cuando combinamos las herencias jerárquica y múltiple. Este problema se llama así porque las clases forman una forma de diamante mientras se heredan entre sí.

Digamos que tenemos un escenario donde tenemos cuatro clases A, B, C y D.

  1. La clase A actúa como clase base.
  2. La clase B es heredada por la clase A.
  3. La clase C también la hereda la clase A.
  4. La clase D la heredan tanto la clase B como la clase C.

problema del diamante en la herencia

Ahora veamos el problema que ocurre con la ayuda de un código.

#include <iostream>
using namespace std;
class A {
 public:
  A() { cout << "Constructor A here!" << endl; }
};

class B : public A {
 public:
  B() { cout << "Constructor B here!" << endl; }
};

class C : public A {
 public:
  C() { cout << "Constructor C here!" << endl; }
};

class D : public B, public C {
 public:
  D() { cout << "Constructor D here!" << endl; }
};

int main() {
  D d;
  return 0;
}

Producción :

Constructor A here!
Constructor B here!
Constructor A here!
Constructor C here!
Constructor D here!

El resultado anterior muestra que el constructor de la clase A ha sido llamado dos veces porque la clase D obtiene dos copias de la clase A. Uno al heredar la clase B y el otro al heredar la clase C.

Esto da lugar a ambigüedades y se denomina problema del diamante en C++.

Este problema ocurre principalmente cuando una clase hereda de varias clases base heredadas de una clase base común.

Sin embargo, este problema se puede resolver utilizando la palabra clave virtual en C++. Hacemos que las clases de dos padres hereden de la misma clase base que las clases virtuales para que la clase secundaria no obtenga dos copias de la clase abuela común.

Por lo tanto, estamos creando clases virtuales de clase B y clase C en nuestro ejemplo de código.

Veamos la solución a este problema con la ayuda de un ejemplo de código.

#include <iostream>
using namespace std;
class A {
 public:
  A() { cout << "Constructor A here!" << endl; }
};

class B : virtual public A {
 public:
  B() { cout << "Constructor B here!" << endl; }
};

class C : virtual public A {
 public:
  C() { cout << "Constructor C here!" << endl; }
};

class D : public B, public C {
 public:
  D() { cout << "Constructor D here!" << endl; }
};

int main() {
  D d;
  return 0;
}

Producción :

Constructor A here!
Constructor B here!
Constructor C here!
Constructor D here!

Por lo tanto, como se muestra en el resultado anterior, ahora solo obtenemos una copia del constructor de la clase A. La palabra clave virtual le dice al compilador que tanto la clase B como la clase C heredan de la misma clase base A; por lo tanto, debe llamarse una sola vez.

Conclusión

En este artículo, hemos discutido brevemente la herencia y los tipos de herencia. Sin embargo, hemos discutido principalmente dos tipos de herencia: múltiple y jerárquica en detalle, lo que da lugar a un problema conocido como el problema del diamante en la herencia.

El problema del diamante ocurre cuando una clase hereda de más de una clase base, que también se hereda de una única clase base. Sin embargo, este problema se resuelve utilizando la palabra clave virtual en C++.

Artículo relacionado - C++ Inheritance