Search code examples
c++overridingderived

Override pure virtual function with different parameter of derived type


There are a lot of questions about this topic, but however, I didn't find the solution for my following question:

I have the following classes:

1) The pure virtual class

class Employee {
private:
    vector<Employee> vec_employee;

public:
    Employee() {};
    virtual ~Employee() {};
    virtual void set_vec_subordinate(vector<Employee> vec_employee) = 0;
};

2) A derived class

class Worker : Employee{ private: public: };

3) Another derived class which should override the pure virtual method from Employee

class Manager : Employee {
private:
public:
    inline void set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); };
};

What I try to achieve is to override the pure virtual method but use a "different" parameter. So still new to C++ but I think there should be a way to do so, especially because the other parameter is from type Worker which is a derived class from Employee.


Solution

  • There is no way to do exactly what you plan to do (and there is good reason for that).

    Your code is also inherently broken, as you use the type vector<Employee>, which requires objects of type Employee - which cannot exist, as Employee is an abstract class. You may wish to use a vector of a reference type, e.g., vector<shared_ptr<Employee>> instead. (The rest of this answer glosses over this fact to make it more readable.)

    Note also that void Manager::set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); }; would cause an infinite loop (probably resulting in a stack overflow) when called, as it will just keep calling itself.

    The class Employee has a contract with its users, that says the following code must be valid (assuming given get_boss and get_workers functions):

    Employee& boss = get_boss();
    vector<Employee> subordinate_vec = get_workers();
    boss.set_vec_subordinate(subordinate_vec);
    

    Now, this might not make any semantic sense for your application, but the syntax of the programming language means that this must be possible. Some programming languages (not C++!) allow covariant calls similar to this:

    Employee& boss = get_boss();
    vector<Worker> subordinate_vec = get_workers();
    boss.set_vec_subordinate(subordinate_vec);  // Invalid C++: `vector<Worker` cannot be converted to `vector<Employee>` implicitly
    

    While it is indeed possible to create a container in C++ that behaves in a way so that this use is possible, it is easier to deal with it is by making the set_vec_subordinate function a template that requires an arbitrary container of objects that are implicitly convertible or derived from Employee - and then just converting the objects during the copy operation (since the vector is not movable in that case anyway).

    The second idea is that it should be possible to change the signature of a function when overriding it. This is kind of possible in C++ by implementing the base case (which needs to be binary compatible with - a.k.a. equal to - the signature of the Employee version, as it will be called for that case as well) and then adding additional overloads. For example, you could do something along the lines of:

    class Manager : Employee {
    private:
    public:
        inline void set_vec_subordinate(vector<Employee> vec_employee) override { this->vec_employee = std::move(vec_employee); };
        inline void set_vec_subordinate(vector<Worker> const& vec_worker) {
            vec_employee = std::vector<Employee>(vec_worker.begin(), vec_worker.end());  // copy convert all elements
        };
    };