Lesson 3 · 3 of 20
Inheritance and virtual functions · C++
Inherit from a C++ class and replace its methods with virtual and override, and see object slicing in action, with a staff payroll.

class Manager : public Employee says a manager is an employee: it inherits the name, the base salary and the payslip() method, and adds its own bonus_. `protected` members are visible to derived classes such as Manager, but not to outside code.
Manager's constructor calls the base constructor first, in its initializer list: : Employee(name, base), bonus_(bonus). The employee part is always built before the manager part.
A `virtual` function can have a different version in a derived class, marked with `override` (so the compiler checks that it really replaces one in the base). Manager::pay() reuses the base version through Employee::pay() and adds the bonus: 2800 + 650 = 3450.
The interesting part is that payslip() is only written in Employee, yet calling it on marc uses Manager::pay() and Manager::role(): virtual calls are resolved at run time, from the real object. The same happens through the reference const Employee& ref = marc. The base has a virtual destructor, virtual ~Employee() = default;, so destroying a manager through the base is safe.
By contrast, Employee copy = marc; copies only the employee part: this is slicing. copy is a real Employee, with no bonus, and earns 2800. To get polymorphism you have to work with references or pointers, as in the next lesson.
Code · 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();}Output · 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
Key points
class B : public Amakes B inherit A's members and methods.- A derived class's initializer list builds the base first.
virtualin the base andoverridein the derived class replace a method.- Virtual calls use the object's real type, even from inside the base.
- Copying a derived object into a base variable slices it.
Exercise
Create an Intern class that derives from Employee, earns 60% of the base salary and returns "Intern" from role(). Print the payslip of an intern with a base of 1500 euros.