Overloaded constructor in derived class - c++

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)
{
}

Related

C++ Class Object inside another class

It keeps me getting this error in Event.h:
field ‘group’ has incomplete type ‘Group’
For context, I want to have a class Group which has an owner (from class Person) and it consists of a vector of people (class Person):
Group.h
class Person;
#include "Person.h"
Class Group
{
private:
std::string name;
std::vector<Person> people;
int size = 0;
Person owner;
public:
Group(Person owner);
~Group();
}
In the Person class, I want to have just a vector of lists (class List, not important for this specific error). Note that in the Person class I have a constructor Person(int id);
In the Event class, I want to have a group of people invited that can be saved as a Group class:
Event.h
class Group;
#include "Group.h"
class Event
{
private:
std::string tittle;
std::string description;
bool locked;
bool checked;
Group group;
public:
Event(std::string tittle);
~Event();
}
Why can't I have a Person owner on my group?
Edit:
I don't know why, but now it works. I guarded everything with just #pragma once and maybe I changed something in the way I compiled. Thanks for all answers :)
You are defining something out of order. Perhaps the #ifdef guards.
This compiles just fine:
class Person {};
class Group
{
private:
std::string name;
std::vector<Person> people;
int size = 0;
Person owner;
public:
Group( Person owr );
~Group();
};
class Event
{
private:
std::string tittle;
std::string description;
bool locked;
bool checked;
Group group;
public:
Event(std::string tittle);
~Event();
};
Godbolt: https://godbolt.org/z/f785vK1dq
The following works fine for me (Online Demo):
Person.h
#ifndef Person_H
#define Person_H
class Person
{
};
#endif
Group.h
#ifndef Group_H
#define Group_H
#include "Person.h"
#include <string>
#include <vector>
class Group
{
private:
std::string name;
std::vector<Person> people;
int size = 0;
Person owner;
public:
Group(Person owner) : owner(owner) {}
};
#endif
Event.h
#ifndef Event_H
#define Event_H
#include "Group.h"
#include <string>
class Event
{
private:
std::string tittle;
std::string description;
bool locked = false;
bool checked = false;
Group group;
public:
Event(std::string tittle) : tittle(tittle), group(Person{}) {}
};
#endif
main.cpp
#include <iostream>
#include "Event.h"
int main()
{
Event evt("title");
return 0;
}

How to get base object's data in a new derived object?

(Beginner in OOP.)
I have a person class which stores the name of the person. In a derived class instance printer, I need that name so that I can do further tasks with it.
#include <iostream>
#include <string>
class Person{
public:
std::string name;
};
class Printer: public Person{
public:
void print(){
printf("%s", this->name.c_str());
}
};
int main() {
Person one;
one.name = "john";
Printer printer;
printer.print();
return 0;
}
What am I not doing to have printer see the data in one ? I'd be having several printer-like objects so storing "john" only once is the goal here.
You have made the member vars public but this is not the right approach for the OOP, the right one is to have them under private access specifier and use setters and getters.
Now to your mistakes:
You use void for main but with c++ you can only use int for it.
You use std::string as an argument for printf but it can't accept it. (I passed the c_string of the std::string to correct that).
You use an object, from the parent class, and give it a name then use another object, from the driven one, to print the name of the first one. (I used only one)
#include <iostream>
#include <string>
class Person{
public:
std::string name;
};
class Printer: public Person{
public:
void print(){
printf("%s",this-> name.c_str());
}
};
int main() {
Printer printer;
printer.name = "name";
printer.print();
}
After your comments, I have updated Printer class to do your inttent
#include <iostream>
#include <string>
class Person{
public:
std::string name;
};
class Printer{
public:
void print(const Person& person ){
printf("%s", person.name.c_str());
}
};
int main() {
Person one;
one.name = "name";
Printer printer;
printer.print(one);
}

C++ How to instantiate abstract parent class constructor from child class

I have an abstract class, that has two variables. I want to instantiate those variables through the constructor.
Then I want to instantiate those variables from the child classes constructors, but it giving me a casting error?
#ifndef Employee_Interface_H
#define Employee_Interface_H
#include <iostream>
using namespace std;
class Employee {
private:
double salary = 0;
double sales = 0;
double bonus = 0;
public:
Employee(double empSalary, double empSales) {
salary = empSalary;
sales = empSales;
}
void virtual calculateBonus() = 0;
};
class Staff : public Employee {
public:
Staff(double empSalary, double empSales) {
Employee(empSalary,empSales);
}
void calculateBonus() {
//20% of salary
}
};
#endif
`
Instead of this:
Staff(double empSalary, double empSales) {
Employee(empSalary,empSales);
}
Use this instead:
Staff(double empSalary, double empSales) :
Employee(empSalary, empSales)
{
}
You have to put the base class constructor call in the derived class constructor's member-initialization-list - after the : marker, but before the constructor's body definition.

Inheritance and Multiple Constructor

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.)

QSharedDataPointer with forward-declared class

The Qt documentation suggests that using the QSharedDataPointer with a visible implementation of its inferior is not typical.
So according to the small example snipped in the docs, I came up with the following source (SSCCE).
The interface: Model.h
The interface is straight forward, just the forward declaration of the private class and the handle class, with copy-ctor and d-tor declared:
#include <QtCore/QSharedDataPointer>
class ModelPrivate;
class Model {
public:
Model();
Model(const Model &other);
~Model();
QSharedDataPointer<ModelPrivate> d;
};
Private header: Model_p.h
Just declares and defines the inferior class.
#include <QSharedData>
class ModelPrivate:
public QSharedData {
public:
};
Implementation: Model.cc
Consisting of the implementation of the c-tors/d-tor, taken from the docs.
#include "Model.h"
#include "Model_p.h"
class ModelPrivate:
public QSharedData {
};
Model::Model():
d(new ModelPrivate()) {
}
Model::Model(const Model &other):
d(other.d) {
}
Model::~Model() {
}
Use case: main.cc
Where it all failed.
#include <QString>
#include "Model.h"
int main(int argc, char *argv[]) {
QString s1, s2;
s2 = s1;
Model m1, m2;
m2 = m1;
}
Just two instances and an assignment, as one would do with any other shared class as well. However, it fails badly because of
invalid use of incomplete type 'class ModelPrivate'
I can't figure out how to make this work the expected way according to the documentation, i.e. without fully declaring the private class in the header as well. I know it works when doing so but I'd like to understand the docs. The example of assigning shared classes is included in the docs as well. From the above-linked docs:
The copy constructor is not strictly required here, because class
EmployeeData is included in the same file as class Employee
(employee.h). However, including the private subclass of QSharedData
in the same file as the public class containing the QSharedDataPointer
is not typical. Normally, the idea is to hide the private subclass of
QSharedData from the user by putting it in a separate file which would
not be included in the public file. In this case, we would normally
put class EmployeeData in a separate file, which would not be included
in employee.h. Instead, we would just predeclare the private subclass
EmployeeData in employee.h this way:
I suppose compilation fails at the operator= that is used when assigning the Model.
You have several major issues with your concept:
You do need to have the private class in separate files to do this nice unlike your original idea.
Regardless that you are writing that you used the concept of the original example from the documentation, you simply did not. You changed the copy constructor concept to copy assighment. Naturally, you need to reimplement that operator, respectively.
Here is my working example of the rewrite for the official example as I think it is better to customize that for the posterity than your diverged example to be more inline with upstream for better comprehension:
main.cpp
#include "employee.h"
int main()
{
Employee e1(1001, "Albrecht Durer");
Employee e2 = e1;
Emplyoee e3;
e3 = e2;
e1.setName("Hans Holbein");
}
employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include <QSharedDataPointer>
#include <QString>
class EmployeeData;
class Employee
{
public:
Employee();
Employee(int id, QString name);
Employee(const Employee &other);
Employee& operator =(const Employee &other);
~Employee();
void setId(int id);
void setName(QString name);
int id() const;
QString name() const;
private:
QSharedDataPointer<EmployeeData> d;
};
#endif
employee_p.h
#ifndef EMPLOYEE_P_H
#define EMPLOYEE_P_H
#include <QSharedData>
#include <QString>
class EmployeeData : public QSharedData
{
public:
EmployeeData() : id(-1) { }
EmployeeData(const EmployeeData &other)
: QSharedData(other), id(other.id), name(other.name) { }
~EmployeeData() { }
int id;
QString name;
};
#endif
employee.cpp
#include "employee.h"
#include "employee_p.h"
Employee::Employee()
{
d = new EmployeeData;
}
Employee::Employee(int id, QString name)
{
d = new EmployeeData;
setId(id);
setName(name);
}
Employee::Employee(const Employee &other)
: d (other.d)
{
}
Employee& Employee::operator =(const Employee &other)
{
d = other.d;
return *this;
}
Employee::~Employee()
{
}
void Employee::setId(int id)
{
d->id = id;
}
void Employee::setName(QString name)
{
d->name = name;
}
int Employee::id() const
{
return d->id;
}
QString Employee::name() const
{
return d->name;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
HEADERS += employee.h employee_p.h
SOURCES += main.cpp employee.cpp
The problem is in deed the assignment operator of the d member that is declared and defined via template in the QSharedDataPointer class.
The solution is as trivial as moving the assignment operator of the shared class into the module:
New interface: Model.h
#include <QtCore/QSharedDataPointer>
class ModelPrivate;
class Model {
public:
Model();
Model(const Model &other);
Model &operator =(const Model &other); /* <-- */
~Model();
QSharedDataPointer<ModelPrivate> d;
};
Private header: Model_p.h
#include <QSharedData>
class ModelPrivate:
public QSharedData {
public:
};
Implementation: Model.cc:
#include "Model.h"
#include "Model_p.h"
Model::Model():
d(new ModelPrivate()) {
}
Model::Model(const Model &other):
d(other.d) {
}
Model::~Model() {
}
Model &Model::operator =(const Model &other) {
d = other.d;
return *this;
}
Use case: main.cc
#include <QString>
#include "Model.h"
int main() {
QString s1, s2;
s2 = s1;
Model m1, m2;
m2 = m1;
}
Project file: example.pro
TEMPLATE = app
TARGET = example
QT = core
HEADERS += Model.h Model_p.h
SOURCES += Model.cc main.cc
This in fact is what other classes in the Qt universe itself are implemented like. For example, consider QTextCursor.