Question

I am trying the derived class example from TCPL.

Manager is kind of employee with additional info of level. I kept getting the error:

no matching function for call to employee::employee() 
in the constructor of manager::manager()

All members of employee are public and accessible. What is wrong with the manager constructor?

#include <iostream>
#include <string>
using namespace std;


class employee{
  public:
    enum type {M,E};
    type hier;
    string id;
    employee(string idd):hier(E){id=idd;};
};

class manager: public employee{
  public:
    int level;
    manager(string idd, int lv){hier=employee::M; id=idd;level=lv;};
};

void print(employee *x){
  if(x->hier == employee::E){
    cout<<"I am employee with id "<<x->id<<endl;
}
  else{
    cout<<"I am manager with id "<<x->id<<endl;
    manager* y=static_cast<manager *>(x);
    cout<<"My level is "<<y->level<<endl;
  }
}

int main(){
  employee t("334");
  manager u("223", 2);
  print(&t);
  print(&u);
}

Second version The previous version was bad in terms of encapsulation

This is the new version

#include <iostream>
using namespace std;

enum type {M, E};

class employee{
  string id;
  type hier;
  public:
    employee(string idd, type hi=E):hier(hi),id(idd){}
    string whatid(){return id;}
    type whattype(){return hier;}
};

class manager: public employee{
  int level;
  public:
    manager(string idd, int lv):employee(idd,M),level(lv){}
    int whatlv(){return level;}
};

Instead of directly accessing the private member of employee and manager, I made members private and use a function to access them.

#include <iostream>
#include <string>
#include "manager_employee.h"
using namespace std;

void print(employee *x){
  if(x->whattype() == E){
    cout<<"I am employee with id "<<x->whatid()<<endl;
  }
  else{
    cout<<"I am manager with id "<<x->whatid()<<endl;
    manager *y=(manager *)x;
//    manager* y=static_cast<manager *>(x);
    cout<<"My level is "<<y->whatlv()<<endl;
  }
}

int main(){
  employee t("334", E);
  manager u("223", 2);
  print(&t);
  print(&u);
}
Was it helpful?

Solution

By declaring a constructor in employee, you remove its default constructor; so you can't create one without specifying the ID.

This means that any derived classes will need to provide the ID to the base-class constructor:

manager(string idd, int lv) : employee(idd) {hier=employee::M; level=lv;}
//                            ^^^^^^^^^^^^^

For consistency, you might like to initialise level in the initialiser list rather than the constructor body; and it might make more sense to initialise hier to the correct value via another parameter in the employee constructor, rather than giving it a default value then overwriting it:

employee(string idd, type hier = E) : hier(hier), id(idd) {}
manager(string idd, int lv) : employee(idd, M), level(lv) {}

OTHER TIPS

If you have any explicit constructor for a class, the default constructor goes out of existence.

So for that reason, when you initialize an object of the derived class, it tries to initialize the base class members as well. And as you have not given a constructor taking no arguments, this error is thrown.

Either define a default constructor for employee or try calling the base class constructor as:

manager(string idd, int lv):employee(idd){//your code}

Manager constructor should call base class ctor in its initialization list:

manager(string idd, int lv) : employee(idd) {hier=employee::M; id=idd;level=lv;}

Also consider using initlization list for other members in your classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top