Inheritance and Multiple Constructor - c++

Okay so I have this person class.
#ifndef PERSON_H
#define PERSON_H
#include<string>
using namespace std;
class Person
{
protected:
string name;
int age;
public:
Person();
Person(string newname, int newage);
void SetName(string n);
void SetAGe(int a);
string GetName();
int GetAge();
};
#endif
And the following person.cpp file.
#include "Person.h"
Person::Person(string newname, int newage){
name = newname;
age = newage;
}
And this Employee.h and .cpp file
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include<string>
#include "Person.h"
using namespace std;
class Employee : public Person
{
protected:
float payrate;
public:
//Member functions
Employee() : Person(){ payrate = 10; }; //Constructor
Employee(float newpay); //Constructor
void SetPayrate(float p);
float GetPayrate{ return p; }
#endif
Here's the cpp I had forgotten
#include "Employee.h"
Employee::Employee(float pay) : Person()
{
payrate = pay;
}
And this is supposed to be able to use this line of code
Employee b("Jane", 21, 12.38);
To create an employee with the name Jane, age 21, and payrate of 12.38, but it says that there is no method of the matching arguments. Am I missing something basic? Thanks.

Your Employee class has two explicitly declared constructors:
Employee() : Person(){ payrate = 10; }; //Constructor
Employee(float newpay); //Constructor
The compiler gives you a copy constructor. Given these, you can construct an Employee using one of the three constructors only.
Employee e1; // OK. Uses the first constructor.
Employee e2(2.4f); // OK. Uses the second constructor.
Employee e3(e2); // OK. Uses the copy constructor
Employee e4 = e2; // OK. Uses the copy constructor
Any other way of constructing an Employee is not allowed. If you want to construct an Employee using
Employee e5("Jane", 21, 21.38);
you have declare a constructor that can accept those as arguments. E.g.
Employee(std::string const& name, int age, float payrate);

Constructors are not inherited, and the compiler won't create new constructors like this for you.
You didn't write a constructor Employee(string, int, float), so you can't call it.
If you add one, then you can:
// in the Employee class
Employee(string newname, int newage, float newpayrate)
: Person(newname, newage)
{
payrate = newpayrate;
}
You can, of course, put it all on one line if you want.
You could also put the definition in Employee.cpp, if you want. (Either way works.)

Related

Compilation error on diamond problem(inheritance)

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;
}
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
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:
Decide what will be the default name and age for a Person derived class like Employee, Student.
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 } {}

No definition in cpp composition when I define in function

#include <iostream>
using namespace std;
class Date{
private:
int day;
int month;
int year;
public:
Date(int dy,int mt,int yr){
day=dy;
month=mt;
year=yr;
}
void showDate(){
cout<<day<<"/"<<month<<"/"<<year<<endl;
}
};
class Human{
private:
string name;
Date birthDay;
public:
Human(string nm,Date bd):name(nm),birthDay(bd){};
showHumanInfo(){
cout<<"The person named : "<<name<<" was born : ";
birthDay.showDate();
}
};
int main()
{
Date birthday(1,2,1995);
Human h1("alek",birthday);
h1.showHumanInfo();
return 0;
}
This works, but why it doesn't work when I do the following?
#include <iostream>
using namespace std;
class Date{
private:
int day;
int month;
int year;
public:
Date(int dy,int mt,int yr){
day=dy;
month=mt;
year=yr;
}
void showDate(){
cout<<day<<"/"<<month<<"/"<<year<<endl;
}
};
class Human{
private:
string name;
Date birthDay;
public:
Human(string nm,Date bd){
name = nm;
birthDay = bd;
}
showHumanInfo(){
cout<<"The person named : "<<name<<" was born : ";
birthDay.showDate();
}
};
int main()
{
Date birthday(1,2,1995);
Human h1("alek",birthday);
h1.showHumanInfo();
return 0;
}
I have problem like that. Why can't I use date class in a human class?
When I change human public class like that
public:
human(){
// ...
}
It not working it thing is the same think but not adding date class in human class.
In the definition of a constructor, all member variables must be initialized before the body of the constructor is executed. Since Date doesn't have a default constructor, there is no way to initialize it
Human(string nm, Date bd)
{ // birthDay must be initialized before this point
// ...
birthDay = bd; // this is assignment, which is too late
}
The fix is to either give Date a default constructor, if that makes sense, or to initialize birthDay in a member initializer list, as you did in the first example code.
I think problems comes from "birthday = bd;"
It has been a while since the last time I coded in C++ but if I am not wrong, using constructor initialiser and using equal operator are not the same.
You should override "=" operator to use it with your object.
About his

C++ - Unable to inherit from base class | Gives empty values

I guess I am doing something wrong here in the below code. I want to inherit the methods of class Person in class Employee.
#include<bits/stdc++.h>
using namespace std;
class Person{
private:
string name;
int age;
public:
Person(string name, int age){ //Base parameterized constructor
name = name;
age = age;
}
void getName(){
cout<<"Name: "<<name<<endl;
}
void getAge(){
cout<<"Age: "<<age<<endl;
}
};
class Employee: public Person{ //Default inheritance type is private
private:
int employeeID;
public:
Employee(string name, int age, int id) : Person(name, age){ //Derived parameterized constructor
employeeID = id;
}
void getEmployeeDetails(){
getName();
getAge();
cout<<"Employee ID: "<<employeeID<<endl;
}
};
int main(){
Employee* e = new Employee("John", 24, 14298);
e->getEmployeeDetails();
return 0;
}
I am getting the below output:
Name:
Age: 0
Employee ID: 14298
Please let me know what am I missing here. Any help would be appreciated!
The issue is not with inheritance, but with the fact that Person never initializes any of its fields.
This code:
Person(string name, int age){ //Base parameterized constructor
name = name;
age = age;
}
assigns local variable name to itself and same with age, because parameters shadow class member names. Member objects with the same name are never initialized.
Three solutions possible (listed in subjective order in which I prefer them):
Use member initializer list to initialize your members:
Person(string name, int age) : name{name}, age{age}
{
}
Use different names
Person(string providedName, int providedAge)
{
name = providedName;
age = providedAge;
}
Use this to disambiguate objects
Person(string name, int age){ //Base parameterized constructor
this->name = name;
this->age = age;
}
Nothing to do with inheritance, the code would have been wrong anyway.
This
Person(string name, int age){ //Base parameterized constructor
name = name;
age = age;
}
should be this
Person(string n, int a){
name = n;
age = a;
}
Because your constructor parameter declaration names are the same as your member variables, the member variables are hidden and you were just assigning the parameters to themselves.
A better way to write the same code is to use an initialiser list
Person(string name, int age) : name(name), age(age)
}
Initialiser lists have a couple of advantages, one of them is that there's no ambiguity, you can have the parameter names the same as the member variable names. The other (more important) is that in general, initialisation is more efficient than assignment.

not able to implement my simple friend function C++

take a look at friend function i am trying to implement
#include <iostream>
#include <string>
using namespace std;
class Customer {
friend void displayInfo(Customer, City);
private:
int custNum;
int zipCode;
};
class City {
friend void displayInfo(Customer, City);
string cityName;
int zipCode;
};
void displayInfo(Customer cus, City city) {
cout << cus.custNum; //compiler error - Inaccessible
}
I understand it is inaccessible. However i have the friend function already defined in the class. So why it is not accessible? Thank you
While you are declaring displayInfo() function as a friend of City and Customer classes, the classes City and Customer given to displayInfo as parameters(i.e. in the declaration) are not defined yet.
If you simply add two lines to the top of your code, as shown here, it does compile.
class City;
class Customer;
Tested code. Only necessary to add class City;
#include <iostream>
#include <string>
using namespace std;
class City;
class Customer {
friend void displayInfo(Customer, City);
private:
int custNum;
int zipCode;
};
class City {
friend void displayInfo(Customer, City);
string cityName;
int zipCode;
};
void displayInfo(Customer cus, City city) {
cout << cus.custNum; //compiler error - Inaccessible
}

Overloaded constructor in derived class

I have the base class Manager and the derived class Worker, the inheritance seem to work properly - I've created a new object of the derived class using it's default constructor and i can output properly.
but now I want to make an overloaded constructor for the derived class (Worker) and there seem to be a compilation error, I tired to look for an answer but I didn't found one.
why the compiles says that Worker doesn't have id, name and salary fields? I've created a derived class by the book and created ctors for it.
Manager header:
#include <string>
#ifndef MANAGER_H
#define MANAGER_H
class Manager
{
public:
Manager (); //ctor
Manager (std::string, std::string, float, int); //overloaded ctor
friend void display (Manager&); //friend function is declared
~Manager (); //dtor
protected:
std::string id;
std::string name;
float salary;
private:
int clearance;
};
Manager cpp:
#include <iostream>
#include "Manager.h"
#include "Worker.h"
Manager::Manager() //default ctor
{
id = "M000000";
name = "blank";
salary = 0;
clearance = 0;
}
Manager::Manager(std::string t_id, std::string t_name, float wage, int num): id (t_id), name (t_name), salary(wage), clearance (num)
{
//overloaded ctor
}
Manager::~Manager()
{
//dtor
}
Worker header:
#include <string>
#ifndef Worker_H
#define Worker_H
class Worker: public Manager
{
public:
Worker();
Worker (std::string, std::string, float, int);
~Worker();
friend void display (Worker&); //friend function is declared
protected:
int projects;
private:
};
#endif // Worker_H
Worker cpp:
#include <iostream>
#include "Manager.h"
#include "Worker.h"
Worker::Worker() //default ctor
{
id = "w000000";
name = " - ";
salary = 0;
projects = 0;
}
Worker::Worker(std::string t_id, std::string t_name, float wage, int num) : id (t_id), name (t_name), salary (wage), projects (num);
{
//ctor
}
Worker::~Worker()
{
//dtor
}
Worker::Worker(std::string t_id, std::string t_name, float wage, int num) : id (t_id), name (t_name), salary (wage), projects (num)
{
//ctor
}
here you initialize the members id,name, salary and clearance defined in base class. you need to pass it to the base class constructor for initialization. you cannot initialize them directly.
id, name and clearance are protected so you can access them in derived class but you cannot initialize them directly using initialization list. either you can initialize inside the constructor or make a call to base constructor in initialization list.
Worker::Worker(std::string t_id, std::string t_name, float wage, int num):Manager(t_id,t_name,wage,0), projects (num)
{
//ctor
}
Derived classes don't see private members of their base class. You have to delegate the constructor.
Your Worker constructors should be like:
Worker::Worker() : Manager("w000000", " - ", 0, 0) {}
Worker::Worker(std::string t_id, std::string t_name, float wage, int num) :
Manager(t_id, t_name, wage, num)
{
}