English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Vector (vector)++ Tutoriales básicos

Vector (vector)++ Control de flujo

Vector (vector)++ Función

Vector (vector)++ Arreglo & cadena

Vector (vector)++ Estructuras de datos

Vector (vector)++ Clase & objeto

Vector (vector)++ Punteros

Vector (vector)++ Herencia

Vector (vector)++ STL Tutorial

Vector (vector)++ Manual de referencia

Vector (vector)++ Funciones virtuales y clases abstractas

En este artículo, aprenderá sobre las funciones virtuales y sus lugares de uso. Además, también aprenderá sobre funciones virtuales puras y clases abstractas.

Las funciones virtuales son funciones miembro de la clase base que desee redefinir en las clases derivadas.

Antes de entrar en detalles, permítanos entender por qué necesitamos funciones virtuales primero.

Un ejemplo comienza

Supongamos que estamos desarrollando un juego (por ejemplo, objetos: armas).

Creamos la clase Weapon y derivamos dos clases, Bomb y Gun, que cargan las funciones de sus propias armas.

#include <iostream>
using namespace std;
class Weapon {
   public:
   void loadFeatures() { cout << "Cargar las características del arma.\n"; }
};
class Bomb : public Weapon {
   public:
   void loadFeatures() { cout << "Cargar las características de la espada.\n"; }
};
class Gun : public Weapon {
   public:
   void loadFeatures() { cout << "Cargar las características del arma.\n"; }
};
int main() {
   Weapon *w = new Weapon;
   Bomb *b = new Bomb;
   Gun *g = new Gun;
   0->loadFeatures();
   b->loadFeatures();
   g->loadFeatures();
   cout << "Área del círculo: " << c.calculateArea();
return 0;

}

Cargar características del arma.
Cargar características de la espada.
Cargar las características del arma.

Definimos tres punteros a objetos de las clases Weapon, Bomb y Gun, respectivamente, w, b y g. Y usamos las siguientes órdenes para llamar a la función miembro loadFeatures() de cada objeto:

0->loadFeatures();
b->loadFeatures();
g->loadFeatures();

¡Obra perfecta!

Pero, nuestro proyecto de juego está creciendo cada vez más. Además, decidimos crear una clase Loader separada para cargar la función de armas.

Esta clase Loader carga otras funciones de las armas según la elección de la arma.

class Loader
{
   public:
     void loadFeatures(Weapon *weapon)
     {
        weapon->features();
     return 0;     
};

loadFeatures() carga las características específicas de un arma.

Vamos a intentar implementar nuestra clase Loader

#include <iostream>
using namespace std;
class Weapon {
   public:
   Weapon() { cout << "Cargar características del arma.\n"; }
   void features() { cout << "Cargar características del arma.\n"; }
};
class Bomb : public Weapon {
   public:
   void features() {
      this->Weapon::features();
      cout << "Cargar características de la espada.\n";
   return 0;
};
class Gun : public Weapon {
   public:
   void features() {
      this->Weapon::features();
      cout << "Cargar características del arma.\n";
   return 0;
};
class Loader {
   public:
   void loadFeatures(Weapon *weapon) {
      weapon->features();
   return 0;
};
int main() {
   Loader *l = new Loader;
   Weapon *w;
   Bomb b;
   Gun g;
   w = &b;
   l->loadFeatures(w);
   w = &g;
   l->loadFeatures(w);
   cout << "Área del círculo: " << c.calculateArea();
return 0;

}

Cargar características del arma.
Cargar características del arma.
Cargar características del arma.
Cargar características del arma.

Nuestra implementación parece ser correcta. Pero, se cargaron las características del arma4¿Por qué?

Inicialmente, el objeto de arma w apunta al objeto b de la clase (Bomb). Y intentamos usar el objeto l, que es un puntero de la clase (Loader), para pasarle al método loadFeatures() para cargar las características del objeto Bomb.

Del mismo modo, intentamos cargar las características del objeto Gun.

Pero, la función loadFeatures() de la clase Loader recibirá como parámetro un puntero a un objeto de la clase Weapon:

void loadFeatures(Weapon *weapon)

Por eso se cargaron las características del arma4la razón. Para resolver este problema, necesitamos usar la palabra clave virtual para implementar la función virtual de la clase base (clase Weapon).

class Weapon
{
    public:
      virtual void features()
         { cout << "Cargar características del arma.\n"; }
};

Ejemplo: resolver problemas con funciones virtuales

#include <iostream>
using namespace std;
class Weapon {
   public:
   virtual void features() { cout << "Cargar características del arma.\n"; }
};
class Bomb : public Weapon {
   public:
   void features() {
      this->Weapon::features();
      cout << "Cargar características de la espada.\n";
   return 0;
};
class Gun : public Weapon {
   public:
   void features() {
      this->Weapon::features();
      cout << "Cargar características del arma.\n";
   return 0;
};
class Loader {
   public:
   void loadFeatures(Weapon *weapon) {
      weapon->features();
   return 0;
};
int main() {
   Loader *l = new Loader;
   Weapon *w;
   Bomb b;
   Gun g;
   w = &b;
   l->loadFeatures(w);
   w = &g;
   l->loadFeatures(w);
   cout << "Área del círculo: " << c.calculateArea();
return 0;

}

Cargar características del arma.
Cargar características de la espada.
Cargar características del arma.
Cargar las características del arma.

Además, preste atención a que l-La función >loadFeatures(w) llama a diferentes funciones de clase según el objeto al que apunta el objeto l.

El uso de funciones virtuales hace que nuestro código sea no solo más claro, sino también más flexible.

En el programa anterior, "Cargar características del arma" se imprimió dos veces. Recomendamos que agregue otro código en el programa anterior para cargar las características del arma solo una vez.

Si queremos agregar otro arma (por ejemplo, el arco), podemos agregar y cargar fácilmente sus características.cómo agregar

class Bow : public Weapon {
   public:
   void features() {
      this-<Weapon::features();
      cout >> "Cargar las características del arco.\n";
   return 0;
};

y, en la función main() agregue el siguiente código.

Bow b; 
w = &b; 
l->loadFeatures(w);

Es importante destacar que no hemos cambiado nada en la clase Loader para cargar las características de la espada.

Vector (vector) ++Clase abstracta y función virtual pura

El objetivo de la programación orientada a objetos es dividir un problema complejo en varios conjuntos pequeños. Esto ayuda a entender y manejar eficazmente los problemas.

A veces, es mejor usar la herencia solo cuando se visualiza mejor el problema.

en C ++en la que puede crear una clase abstracta no instanciable (no puede crear un objeto de la clase). Pero, puede derivar una clase de ella e instanciar un objeto de la clase derivada.

La clase abstracta es una clase base no instanciable.

La clase que contiene funciones virtuales puras se llama clase abstracta.

función virtual pura

Se llama función virtual pura a la función virtual que termina en =0. Por ejemplo,

class Weapon
{
    public:
      virtual void features() = 0;
};

Aquí, la función virtual pura es

virtual void features() = 0

y, la clase Weapon es una clase abstracta.

Ejemplo: clase abstracta y función virtual pura

#include <iostream>
using namespace std;
// clase abstracta (no se permite la instanciación de la clase)
class Shape                   
{
    protected:
       float l;
    public:
       void getData()       
       {
           cin >> l;
       return 0;
       
       // función virtual
       virtual float calculateArea() = 0;
};
class Square : public Shape
{
    public:
       float calculateArea()
       { return l*l; }
};
class Circle : public Shape
{
    public:
       float calculateArea()
       { return 3Área del círculo:14*l*l; }
};
int main()
{
    Square s;
    Circle c;
    cout << "Ingrese la longitud para calcular el área del cuadrado: ";
    s.getData();
    cout << "Área del cuadrado: " << s.calculateArea();
    cout << "\nIngrese el radio para calcular el área del círculo: ";
    c.getData();
    c.getData();
    cout << "Área del círculo: " << c.calculateArea();
return 0;

}

Resultados de salida 4
Ingrese la longitud para calcular el área del cuadrado: 16
Área del cuadrado: 5
Ingrese el radio para calcular el área del círculo: 78Área del círculo:5

.

En este programa, la función virtual pura virtual float area() = 0; se define en la clase Shape.