Home > Software design >  No matching function for call to ‘student::student()’ error [duplicate]
No matching function for call to ‘student::student()’ error [duplicate]

Time:09-17

What is wrong with the following code with respect to inheritance? Getting no matching function for call to ‘student::student()’ error.

class student {
 private:
  string firstname;
  string lastname;

 public:
  student(string fname, string lname) {
    firstname = fname;
    lastname = lname;
  }
  string getname() { return firstname   lastname; }
  void setfirstname(string fname) { this->firstname = fname; }
};

class undergraduate : public student {
 private:
  double gpa;
  student* stu;

 public:
  undergraduate(string firstname, string lastname, double gpa) {
    stu = new student(firstname, lastname);
    this->gpa = gpa;
  }
};

int main() {
  undergraduate stu1("Sam", "Singh", 4.0);
  stu1.setfirstname("temp");
  cout << stu1.getname();
}

Please point out the mistake and help me in rectifying it. Thanks!

CodePudding user response:

It looks like you might be a Python programmer, so here is your code, re-written in that langage

class student:
    def __init__(self, fname, lname):
        self.firstname = fname;
        self.lastname = lname;

    @property
    def name(self):
        return self.firstname   self.lastname

class undergraduate(student):
    def __init__(self, fname, lname, gpa):
        super().__init__(fname, lname)
        self.gpa = gpa
 
stu1 = undergraduate("Sam", "Singh", 4.0);
stu1.firstname = "temp";
print(stu1.name)

The first thing to notice is that the undergraduate does not contain a student member. Since it inherits from student (is a) there is no need for a member in undergraduate. It's the same for the C class.

However, in the Python code, the undergraduate class calls the student ctor in the body of the undergraduate ctor. That's different from how it works in C . That language uses "initializer lists". These are used to not only call parent ctors but also initialize member variables.

class student {
 private:   // You may want to change to protected so child classes can access
  string firstname;
  string lastname;

 public:
  student(string fname, string lname) {
    firstname = fname;
    lastname = lname;
  }
  string getname() { return firstname   lastname; }
  void setfirstname(string fname) { this->firstname = fname; }
};

class undergraduate : public student {
 private:
  double gpa;
 
 public:
  undergraduate(string firstname, string lastname, double gpa) :
    student(firstname, lastname),  // Call parent ctor
    gpa(gpa)                       // Initialize this->gpa to gpa parameter
  {
      // The initializer list has taken care of everything so there's nothing here
      // But additional code could be added if needed.
  }
};

int main() {
  undergraduate stu1("Sam", "Singh", 4.0);
  stu1.setfirstname("temp");
  cout << stu1.getname();
}

If you are confused about how inheritance works, I strongly recommend you find a good book or tutorial. Answers on SO cannot go into enough detail to fully explain the concepts.
The Definitive C Book Guide and List
Constructors and member initializer lists


RE the original error in the code: the compiler is looking for a default ctor (no parameters) for student but you do not provide one. See: When do we need to have a default constructor?

CodePudding user response:

The undergraduate is a student. Therefore, the construction of undergraduate needs to first construct the parent class student.

Since you have not provided, how to construct the parent student in

 undergraduate(string firstname, string lastname, double gpa) 
 {
    stu = new student(firstname, lastname);
    this->gpa = gpa;
 }

before it comes to the constructor body, the compiler will try to do it for you by calling the default constructor of student. Since the student has parameterized constructor student(string fname, string lname), the compiler will not generate one for you and end up not having a default constructor for student. This leads to the error.

Secondly, you do not require the pointer to the parent, unless you have any other special requirements.

Therefore, you have two different options to solve the issue.

  1. Provide the default constructor for student.
  2. Or initialize the student in the child constructor (undergraduate), removing the redundant pointer to student.

Also use the constructor member initializer list for initializing the member of the class:

undergraduate(string firstname, string lastname, double gpa)
 :  student{ std::move(firstname), std::move(lastname)}
 ,  gpa{ gpa} 
 {}
  • Related