Lección 3 · 3 de 20
Herencia y funciones virtuales · C++
Herede de una clase en C++ y sustituya sus métodos con virtual y override; descubra también el recorte de objetos, con una nómina de empleados.

class Manager : public Employee dice que un jefe es un empleado: hereda su nombre, su sueldo base y el método payslip(), y añade lo suyo, bonus_. Los miembros `protected` se ven desde las clases derivadas, como Manager, pero no desde fuera.
El constructor de Manager llama primero al de la clase base en su lista de inicialización: : Employee(name, base), bonus_(bonus). La parte de empleado siempre se construye antes que la de jefe.
Una función `virtual` puede tener otra versión en la clase derivada, marcada con `override` (así el compilador comprueba que de verdad sustituye a una de la base). Manager::pay() reutiliza la de la base con Employee::pay() y le suma la prima: 2800 + 650 = 3450.
Lo interesante es que payslip() solo está escrito en Employee, pero al llamarlo sobre marc usa Manager::pay() y Manager::role(): las llamadas virtuales se deciden al ejecutar, según el objeto real. Lo mismo ocurre con la referencia const Employee& ref = marc. La base lleva un destructor virtual, virtual ~Employee() = default;, para que destruir un jefe a través de la base sea seguro.
En cambio, Employee copy = marc; copia solo la parte de empleado: es el recorte (*slicing*). copy es un Employee de verdad, sin prima, y cobra 2800. Para aprovechar el polimorfismo hay que trabajar con referencias o punteros, como en la lección siguiente.
Código · main.cpp
#include <iostream>#include <string>class Employee {public: Employee(std::string name, double base) : name_(name), base_(base) {} virtual ~Employee() = default; // virtual: a derived class may replace it with its own version. virtual double pay() const { return base_; } virtual std::string role() const { return "Employee"; } void payslip() const { std::cout << name_ << " (" << role() << "): " << pay() << " EUR\n"; }protected: // visible to derived classes, hidden from the rest std::string name_; double base_;};class Manager : public Employee { // a Manager is an Employee double bonus_;public: Manager(std::string name, double base, double bonus) : Employee(name, base), bonus_(bonus) {} double pay() const override { return Employee::pay() + bonus_; } std::string role() const override { return "Manager"; }};int main() { Employee eva("Eva", 2100); Manager marc("Marc", 2800, 650); eva.payslip(); marc.payslip(); // payslip() is Employee's, but calls Manager::pay const Employee& ref = marc; // a base reference to a Manager std::cout << "Via Employee&: " << ref.pay() << " EUR\n"; Employee copy = marc; // slicing: only the Employee part is copied copy.payslip();}Salida · c++ -std=c++17 main.cpp -o main && ./main
Eva (Employee): 2100 EUR Marc (Manager): 3450 EUR Via Employee&: 3450 EUR Marc (Employee): 2800 EUR
Para recordar
class B : public Ahace que B herede los miembros y métodos de A.- La lista de inicialización de la derivada construye primero la base.
virtualen la base yoverrideen la derivada sustituyen un método.- Las llamadas virtuales usan el tipo real del objeto, también desde la base.
- Copiar una derivada en una variable de la base la recorta.
Ejercicio
Cree una clase Intern que derive de Employee, cobre el 60 % del sueldo base y devuelva "Intern" en role(). Haga la nómina de una becaria con 1500 euros de base.