Start learning free

LESSON 557 OF 568 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Employees and Managers in C++: Inheritance with virtual and override

Practice O(1) Read the full explanation

A company pays every employee a salary. A manager is an employee too, but earns a bonus on top of the salary. Write the two classes so that a manager reuses everything an employee has, and changes only how its pay is worked out.

Implement the class Employee:

  • Employee(name, salary) creates an employee. The name and the salary are private to Employee.
  • pay() returns the salary.
  • describe() returns the text <name> earns <pay>, where the amount is what pay() returns, for example Ana earns 3000.

and the class Manager, which inherits from Employee:

  • Manager(name, salary, bonus) lets the parent's constructor store the name and the salary, and stores the bonus itself, private to Manager.
  • pay() returns the parent's pay() plus the bonus. Call the parent's version, as in the lesson Calling the Parent Method: the salary is private to Employee, and the parent's pay() is what knows how an employee is paid.
  • describe() is not written again: Manager inherits it unchanged. Because describe() calls pay(), a manager's description shows the manager's pay, bonus included.

The input is a list of people, one per line: employee name salary or manager name salary bonus. For each line, the code that tests your classes creates that object and prints what its describe() returns, on a line of its own. The starter code spells these names the way your language does.

 

Example 1:

Input:
    employee Ana 3000
    manager Bob 4000 1000
Output:
    Ana earns 3000
    Bob earns 5000
Explanation:
Ana's pay is her salary. Bob's pay is the parent's pay, his salary 4000, plus his bonus 1000.
Bob's describe() is Employee's describe(), but the pay() it calls is Manager's.

Example 2:

Input:
    manager Cleo 5000 0
    employee Dan 5000
Output:
    Cleo earns 5000
    Dan earns 5000
Explanation: A manager whose bonus is 0 earns exactly the salary, like an employee.

Example 3:

Input:
    manager Eve 7000 2500
    employee Finn 2800
    employee Gus 3100
    manager Hana 6000 500
Output:
    Eve earns 9500
    Finn earns 2800
    Gus earns 3100
    Hana earns 6500
Explanation: Employees and managers come in any order, and each object keeps its own name and numbers.

 

Constraints:

  • 0 <= salary <= 106
  • 0 <= bonus <= 106
  • A name is one word of 1 to 20 English letters. Two people may have the same name.
  • At most 100 people per test case.
STEP 1 OF 8
    Ctrl + Enter to check

    C++ · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Employees And Managers in C++, explained

    Problem overview

    A company pays every employee a salary. A manager is an employee too, but earns a bonus on top of the salary. The task is to write two classes so that a manager reuses everything an employee has and changes only how its pay is worked out.

    Employee has a private name and a private salary. Its pay() returns the salary, and its describe() returns text such as Ana earns 3000, using whatever pay() returns. Manager inherits from Employee. Its constructor takes a name, a salary and a bonus; it lets the parent's constructor store the name and salary and keeps the bonus itself, privately. Its pay() returns the parent's pay plus the bonus. describe() is not written again.

    For Employee("Ana", 3000) the description is Ana earns 3000. For Manager("Bob", 4000, 1000) it is Bob earns 5000: the same describe() code, but a different pay().

    Approach

    The design has three ideas.

    • Inheritance. class Manager : public Employee makes Manager get the name, the salary and both methods. Manager adds only what is new: the bonus.
    • Overriding. Manager replaces pay() with its own version. For that to work when describe() calls pay() from inside Employee, the parent's pay() must be virtual. Then the call picks the version that belongs to the object's real class.
    • Calling the parent's version. The salary is private to Employee, so Manager can't read it. It doesn't need to: Employee::pay() runs the parent's method, and the manager adds its bonus to the result. C++ has no super; the class name and :: do the job.

    Every method does a constant amount of work apart from building the text, which is proportional to the length of the name.

    Step by step

    1. Declare Employee's fields in its private: section: a string name and an int salary. Private means that only code inside Employee can use them, not even Manager.
    2. Store them in the constructor with this->name = name; and this->salary = salary;.
    3. Write pay(), which returns salary, and mark it virtual so that Manager can replace it, even when describe() calls it from inside Employee.
    4. Write describe(). It returns the name, then " earns ", then to_string(pay()), joined with +. It calls pay() instead of reading salary, so on a manager the bonus shows up without a second describe().
    5. Declare Manager with : public Employee. It already has the name, the salary, pay() and describe(). Give it its own private int bonus.
    6. Write the constructor. The header's : Employee(name, salary) runs Employee's constructor first and passes the name and the salary to it, so the private fields are filled in by the code that owns them. The body only stores this->bonus = bonus;.
    7. Override pay() with int pay() override and return Employee::pay() + bonus. Writing plain pay() there would call this same method again and never stop.

    The solution in C++

    class Employee {
    private:
        string name;
        int salary;
    
    public:
        Employee(string name, int salary) {
            this->name = name;
            this->salary = salary;
        }
    
        virtual int pay() {
            return salary;
        }
    
        string describe() {
            return name + " earns " + to_string(pay());
        }
    };
    
    class Manager : public Employee {
    private:
        int bonus;
    
    public:
        Manager(string name, int salary, int bonus) : Employee(name, salary) {
            this->bonus = bonus;
        }
    
        int pay() override {
            return Employee::pay() + bonus;
        }
    };

    A run

    Here are two people from the first example, described through the same method:

    #include <iostream>
    #include <string>
    using namespace std;
    
    // the class above goes here
    int main() {
        Employee ana("Ana", 3000);
        Manager bob("Bob", 4000, 1000);
        cout << ana.describe() << endl;
        cout << bob.describe() << endl;
        Employee* p = &bob;
        cout << p->pay() << endl;
        Employee copy = bob;
        cout << copy.pay() << endl;
    }

    It prints:

    Ana earns 3000
    Bob earns 5000
    5000
    4000

    Manager never defines describe(), yet Bob's description shows 5000. The inherited describe() calls pay(), and because pay() is virtual, an object that is a Manager runs Manager::pay().

    Why virtual matters

    Without virtual, a call to pay() from inside Employee's code always means Employee::pay(), whatever the real type of the object. This version leaves it out:

    #include <iostream>
    #include <string>
    using namespace std;
    
    class Staff {
    private:
        string name;
        int salary;
    public:
        Staff(string name, int salary) {
            this->name = name;
            this->salary = salary;
        }
        int pay() {
            return salary;
        }
        string describe() {
            return name + " earns " + to_string(pay());
        }
    };
    class Boss : public Staff {
    private:
        int bonus;
    public:
        Boss(string name, int salary, int bonus) : Staff(name, salary) {
            this->bonus = bonus;
        }
        int pay() {
            return Staff::pay() + bonus;
        }
    };
    
    int main() {
        Boss bob("Bob", 4000, 1000);
        cout << bob.describe() << endl;
        cout << bob.pay() << endl;
    }

    It prints:

    Bob earns 4000
    5000

    The manager's description ignores the bonus, because describe() is part of Employee and calls Employee's pay(). With virtual it prints 5000, as in the lesson. The keyword override on Manager::pay() adds a safety check: if the signature doesn't match a virtual function of the parent, for example because of a typo in the name, the compiler reports an error instead of quietly creating an unrelated method.

    Details worth knowing

    • Private fields stay private to the class. If Manager::pay() tried to write salary + bonus, the compiler would reject it with 'int Employee::salary' is private within this context. Calling Employee::pay() is the intended route.
    • Objects keep their own type. A Manager variable runs Manager::pay() and an Employee variable runs Employee::pay(). Copying a manager into an Employee variable keeps only the Employee part, which is called slicing: the copy pays 4000 for Bob. Through a pointer or reference to the manager, pay() still gives 5000.
    • The order of construction. The parent's constructor always runs before the child's body, so the child can rely on the parent part being ready.
    • A bonus of 0 makes a manager earn exactly the salary, like an employee.

    Common mistakes

    • Forgetting virtual on the parent's pay(). The code compiles, and managers silently lose their bonus in descriptions.
    • Calling pay() inside Manager::pay() instead of Employee::pay(). The method then calls itself forever.
    • Making name and salary public so that Manager can use them. The lesson keeps them private on purpose; the parent's methods are the way in.
    • Copying the describe logic into Manager. The point of inheritance is that it isn't needed.
    Keep going with C++500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free