Replace shared_ptr object with another one

485 views Asked by At

Basically I have base class Employee with enum class inside it, and derived classes Worker, Intern, Manager with specified field from enum describing them.

class Employee {
public:
    enum class Status {
        Intern,
        Worker,
        Manager
    };
protected:

    int employeeID;
    std::string Name;
    std::string Surname;
    int Salary;
    bool Hired;
...
}

class Worker : public Employee {

protected:

    Status status = Status::Worker;
}

// "Intern" and "Manager" same way.

I store objects in vector<shared_ptr<Employee>> Firm; and modifying them via sourceEmployee[index] reference.

What I want to do is:

Promote/demote employee, how? I want to look for specified employee and check his status. If it's Worker I want to delete Worker class object and make object Manager instead, with all fields saved from Worker like: name, surname etc.

My prototype (does not working) looks like that:

    auto it = std::find_if(sourceEmployee.begin(), sourceEmployee.end(),
                      [&sourceEmployee, id](const auto &obj) { return obj->getID() == id; });
    auto index = std::distance(sourceEmployee.begin(), it);

        switch(sourceEmployee[index]->getStatus()) { // returning status

            case Intern::Status::Intern: // does it recognize object properly?

                auto tmp0 = std::move(*it);
                (*it).reset();                         // ??
                *it = std::make_shared<Worker>(tmp0);

                cout << "Employee " << id << " has been promoted" << endl;
                break;
1

There are 1 answers

5
JaMiT On

This is what I see in your example. The only difference between Employee and its derived classes is that the derived classes each have a Status field. This field serves the same purpose in all derived classes.
Question: Why have derived classes? Just make status part of Employee and assign it the appropriate value as employees are promoted and demoted. Then the answer to your question is that you simply assign status a new value (presumably through a class method).

Maybe you omitted key details. Maybe there are other fields, so there is a reason to have derived classes.
Question if status is going to be the same for all objects of a class, why is it not a static const? (Even then, it feels like data duplication. There may be a better way to accomplish your goal.)

If you want to transform one derived class into another, you probably want to define a constructor for each derived class that takes a reference to the base class as a parameter. This would invoke the copy constructor on the base class, then initialize the fields of the new class. (If there are fields to copy not in the base class, you've got your data organized badly.)

Worker::Worker(const Employee & person) : Employee(person) {}

As for invoking this, it looks like you have unnecessary bookkeeping going on, which could lead to errors. Tough to say, though, since your code is incomplete. Taking a guess as to the surrounding context, something like the following might work:

it->reset(std::make_shared<Worker>(**it));

Of course, whether or not this syntax is correct depends on how it was declared, and on how it was assigned a value (neither of which appear in the question).


Now let's move on to improving your data organization. You might find that instead of deriving from Employee, it would be better to have a Job class from which Intern, Worker, and Manager derive. Then Employee could have a (smart) pointer to Job, where your job-related data would reside. As a benefit, there is no copying required when switching jobs; just delete the old Job object and allocate a new one. (This can be seen as a generalization of the first case I mentioned where status is simply assigned a new value.)