2

I have a parent class: employee with two inherited classes: Hourly and Salary In the parent class I overloaded << so it will output all the variable values from the employee. I need to create 3 new employees: 2 Hourly and 1 Salary, but my constructors don't seem to be working correctly. The program will compile but when I call the Hourly constructor the program stops working (stack overflow?). Here's some code:

class employee
{
    friend ostream& operator<<(ostream& out, const employee& emp);

    public:

    employee ();
    employee(string id, string fname, string lname, string bDate, string hDate, double pay);
    ~employee();
    void setEmpId(string id);
    string getEmpID();
    void setFirstName(string name);
    string getFirstName();
    void setLastName(string name);
    string getLastName();
    void setBirthDate(string birthDate);
    string getBirthDate();
    void setHireDate(string hireDate);
    string getHireDate();
    void setPayRate(double rate);
    double getPayRate();

    protected:

    string employee_id;
    string first_name;
    string last_name;
    string birth_date;
    string hire_date;
    double pay_rate;
};

This is my parent class and here are my two inherited classes:

class Hourly : public employee
{
    public: 

    Hourly(string fname, string lname, string bdate, string hdate, double rate, string id)
    {
        int random = rand() % 1000;
        this->employee_id=id;
        this->first_name=fname;
        this->last_name=lname;
        this->birth_date=bdate;
        this->hire_date=hdate;
        this->pay_rate=rate;
    }
};

The Salary class is essentially the same thing as of right now. Here's where I try to create my Hourly employee:

employee empOne = Hourly("Brian", "Finn", "1/12/1995", "1/12/2015", 7.25, "1215");
cout << empOne;

I know that it never gets past the constructor because I have tried to cout tests and the program never makes it that far.

Mr_Pouet
  • 4,061
  • 8
  • 36
  • 47

3 Answers3

1

You can not do polymorphism with value semantics. It must be reference or pointer, so the object is sliced in its assignment to the employee object and you end up with an employee rather than an Hourly. You could stop this by creating the object on the heap. Also you should be defining your base classes destructor as virtual, otherwise the wrong destructor would be called when deleting through a base class pointer.

Finally you should call the base classes constructor in the derived classes constructor.

With all these changes it works fine for me.

#include <iostream>
#include <string>
#include <cstdlib>

using std::cout;
using std::string;
using std::ostream;

class employee
{
    friend ostream& operator<<(ostream& out, const employee& emp);

    public:
    employee ();
    employee(string const& id, string const& fname, string const& lname, string const& bDate, string const& hDate, double pay)
        : employee_id(id), first_name(fname), last_name(lname), birth_date(bDate), hire_date(hDate), pay_rate(pay)
    {}
    virtual ~employee(){};    

    protected:
    string employee_id;
    string first_name;
    string last_name;
    string birth_date;
    string hire_date;
    double pay_rate;
};

ostream& operator<<(ostream& out, const employee& emp)
{
    out << emp.employee_id;
    return out;
}

class Hourly : public employee
{

public: 
Hourly(string const& fname, string const& lname, string const& bdate, string const& hdate, double rate, string const& id)
    : employee(id, fname, lname, bdate, hdate, rate)
{
    int random = rand() % 1000;
}
};

void printEmployee(employee& e)
{
    cout << e << '\n';
}

int main()
{
    // using reference semantics
    Hourly empOne = Hourly("Brian", "Finn", "1/12/1995", "1/12/2015", 7.25, "1215");
    printEmployee(empOne);

    // using pointer semantics
    employee* empTwo = new Hourly("Dave", "Smith", "1/12/1995", "1/12/2015", 7.25, "1216");
    cout << *empTwo << '\n';
    delete empTwo; // would be better to use a `unique_ptr` and you wont need a delete.
}
Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
1

You problem is that you assign the object to a base class object and then you slice it.

 employee empOne = Hourly("Brian", "Finn", "1/12/1995", "1/12/2015",
 7.25, "1215");

Your constructor tries to the assignment with wrong aliasing and results in a crash (notice the pointer use of this in the constructor). You can overcome the first part by doing initialization in the initializer list of your constructor. However, slicing still occurs.

You should either assign it to its declared class or hold it by base class pointer.

e.g. 1

Hourly empOne = Hourly("Brian", "Finn", "1/12/1995", "1/12/2015", 7.25, "1215");

e.g. 2

employee * empOne = new Hourly("Brian", "Finn", "1/12/1995", "1/12/2015", 7.25, "1215");

For the latter to work you need to define a virtual base class destructor.

virtual ~employee() = default; 
Community
  • 1
  • 1
g24l
  • 3,055
  • 15
  • 28
0

In the assignment statement below Hourly type is sliced.

 employee empOne = Hourly("Brian", "Finn", "1/12/1995", "1/12/2015", 7.25, "1215"); 

I suspect that the following would work

 Hourly hourlyEmp("Brian", "Finn", "1/12/1995", "1/12/2015", 7.25, "1215");
 cout << hourlyEmp;
Community
  • 1
  • 1
alexm
  • 6,854
  • 20
  • 24