Home > OS >  Compilation error on diamond problem(inheritance)
Compilation error on diamond problem(inheritance)

Time:07-24

Why does the code below throw the following compilation error on msvc ?

No default constructor exists for class 'Person'

If I don't create a default constructor in the class Person, then should I delete the constructor of Employee and Student that takes only one argument and call Employee(name,age,grade) and Student(name,age,cl) from ctor of Manager although the Base class constructor is never going to get called from Employee and Student class?

#include<iostream>
#define endl '\n'
using std::cout;

class Person {
    std::string mname;
    int mage;
public:
    //Person() = default;
    Person(const std::string& name, int age) :mname{ name }, mage{ age }{}
};
class Employee :virtual public Person {
    int msalary;
public:
    Employee(const std::string& name, int age, int sal) :Person{ name,age }, msalary{ sal }{}
    Employee(int sal): msalary { sal }{}

};
class Student : virtual public Person {
    int mclass;
public:
    Student(const std::string& name, int age, int cls) :Person{ name,age }, mclass{ cls }{}
    Student(int cls) :mclass{ cls } {}

};

class Manager :public Student, Employee {
private:

public:
    Manager(const std::string& name,int age, int salary,int cl) :Person{name,age}, Student{cl}, Employee{salary} {}
};
int main() {

    Manager manager{ "lorem",40,10000 ,10};

    return 0;
}

CodePudding user response:

Why does the above code throws compilation error

The problem is that before entering the body of the ctor Employee::Employee(int), the default ctor Person::Person() of Person will be used but the compiler will not synthesize the default ctor Person::Person() as the parameterized ctor Person::Person(const std::string&, int) is present.

The error can be reproduced by just the following example:

class Person {
    std::string mname;
    int mage;
public:
    //Person() = default;
    Person(const std::string& name, int age) :mname{ name }, mage{ age }{}
};
class Employee :virtual public Person {
    int msalary;
public:
    Employee(const std::string& name, int age, int sal) :Person{ name,age }, msalary{ sal }{}
//--------------------v--------------------->here Person::Person() is called implicitly
    Employee(int sal):   msalary { sal }{}

};

Demo error

CodePudding user response:

The cause of the problem:

Both Employee and Student have constructors that do not call the only available constructor of the base class Person (requireing name and age parameters). Therefore the compiler will attempt to use a default constuctor fo the base class which is not available.

You can handle it the following way:

  1. Decide what will be the default name and age for a Person derived class like Employee, Student.
  2. Use the defaults to construct the base, e.g.:
static inline const std::string DEFAULT_NAME = "<default_name>";
static inline const int DEFAULT_AGE = 20;
Employee(int sal) : Person(DEFAULT_NAME, DEFAULT_AGE), msalary{ sal } {}
  • Related