Las diferencias entre las funciones virtuales puras y virtuales en C++

Jinku Hu 12 octubre 2023
  1. Funciones virtuales y sus características en C++
  2. Funciones virtuales puras y tipos abstractos en C++
Las diferencias entre las funciones virtuales puras y virtuales en C++

Este artículo describirá las diferencias entre las funciones virtuales puras y virtuales en C++.

Funciones virtuales y sus características en C++

Las funciones virtuales están estrechamente asociadas con el concepto de polimorfismo. En C++, podemos organizar diferentes clases en una jerarquía vinculada donde podrían compartir algunos miembros de datos y tener las mismas funciones de miembro expuestas como la interfaz.

Generalmente, las clases que heredan alguna parte del código de otras clases se denominan clases derivadas, mientras que las que heredan son las clases base. Tenga en cuenta que a veces estos términos pueden usarse indistintamente con nombres de padre-hijo o superclase-subclase. Las funciones que se pueden anular en clases derivadas se denominan funciones virtuales y se declaran con la palabra clave virtual. Las funciones virtuales tienen el mismo nombre dentro de la jerarquía de clases dada, y cada clase derivada puede implementar su propia definición de la función.

Si la función no se reemplaza, el objeto de la clase derivada invoca la función definida en la clase base. El siguiente programa de ejemplo a continuación demuestra el uso básico de funciones virtuales definiendo la función print en las clases Engineer y Employee. Entonces podemos implementar alguna función arbitraria Func que acepta la referencia a Employee y llama a la función print dentro del cuerpo.

Ahora, la implementación de Func puede cambiar varias veces, pero siempre llamará a la función print correspondiente en función del objeto que se pasa como parámetro. Podemos agregar múltiples clases derivadas en la jerarquía de clases Employee. Cada uno de ellos puede / no puede implementar la función print, pero la función Func aceptará sus instancias e invocará la función virtual correcta.

#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

class Employee {
 public:
  Employee(string fn, string ln)
      : first_name(std::move(fn)), last_name(std::move(ln)) {}
  virtual void print() {
    cout << "name: " << first_name << "\n"
         << "last name: " << last_name << "\n";
  };

 protected:
  string first_name, last_name;
};

class Engineer : public Employee {
 public:
  Engineer(string fn, string ln, string sp)
      : Employee(std::move(fn), std::move(ln)), specialization(std::move(sp)) {}

  void print() override {
    Employee::print();
    cout << "specialization: " << specialization << "\n";
  }

 private:
  string specialization;
};

void Func(Employee &em) { em.print(); }

int main() {
  Employee em1("Jim", "Jiao");
  Engineer eng1("Jin", "Baker", "Aerospace Engineering");

  Func(em1);
  cout << "\n";
  Func(eng1);

  return EXIT_SUCCESS;
}

Producción :

name: Jim
last name: Jiao

name: Jin
last name: Baker
specialization: Aerospace Engineering

Funciones virtuales puras y tipos abstractos en C++

Por otro lado, tenemos el concepto de funciones virtuales puras, que se declaran similares a las funciones virtuales regulares e incluyen la notación = 0; al final de la declaración. Estas funciones esencialmente no tienen una definición en la clase base, donde se declaran primero. Por lo tanto, lo más probable es que se definan en las clases derivadas.

Las clases que contienen funciones virtuales puras se denominan clases abstractas y generalmente se utilizan para especificar la interfaz de las clases derivadas. Tenga en cuenta que las clases abstractas no se pueden instanciar directamente.

El siguiente fragmento de código implementa las clases Triangle y Rectangle con la clase base abstracta Shape. En este caso, definimos la función virtual pura printArea en ambas clases derivadas. A veces, una clase derivada puede no definir una función virtual pura heredada, lo que la convierte en otra clase abstracta en la jerarquía de clases dada. Una clase derivada puede heredar múltiples funciones virtuales puras. Si no define ni siquiera uno de ellos, se aplica una clasificación abstracta a la clase.

#include <iostream>
#include <string>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Shape {
 public:
  virtual void printArea() = 0;
};

class Triangle : public Shape {
 public:
  Triangle(double b, double h) : base(b), height(h) {}

  void printArea() override { cout << (base * height) / 2.0; }

 private:
  double base;
  double height;
};

class Rectangle : public Shape {
 public:
  Rectangle(double i1, double i2) : edges({i1, i2}) {}

  void printArea() override { cout << edges[0] * edges[1]; }

 private:
  vector<double> edges;
};

int main() {
  Triangle t1(3, 5);
  t1.printArea();
  cout << "\n";

  Rectangle r1(3, 5);
  r1.printArea();
  cout << "\n";

  return EXIT_SUCCESS;
}

Producción :

7.5
15
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - C++ Function