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);
}
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) {}
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.
Related
Within my vehicle base class, I have a private member variable, string type (for type of vehicle, ie car, motorbike, tricycle, etc).
#pragma once
using namespace std;
#include <string>
#include <iostream>
class vehicle {
public:
vehicle(string reg, string make, string model, int age, string type);
virtual ~vehicle() = default;
virtual double costPerDay() = 0;
protected:
int age;
int perDayCostCap(int costPD);
double penceToPounds(int pence);
private:
const string type;
string const reg, make, model;
};
One of the derived classes, bike, has a numberOfWheels variable which is to be passed into its constructor. I want to initialize the base class constructor with type bicycle or tricycle depending on the numberOfWheels.
I can not figure out how to achieve this, seeing as the base class constructor has to be initialized before the function body of the child class.
The following shows what I would like to achieve (though, I know this is not possible):
bike::bike(int engineCC, int numOfWheels, string reg, string make, string model, int age)
:engineCC(engineCC), numOfWheels(numOfWheels) {
string tricOrBic = (numOfWheels == 2) ? "bicicle" : "tricicle";
vehicle:reg=reg, make=make, model=model, age=age, type=tricOrBic;
};
Like this?
bike::bike(int engineCC, int numOfWheels, string reg, string make, string model, int age)
: vehicle(reg, make, model, age, numOfWheels == 2 ? "bicycle" : "tricycle")
, engineCC(engineCC)
, numOfWheels(numOfWheels)
{
}
This is normal programming, maybe you had some problem I'm not seeing.
I'm having difficulties in defining a constructor for a class that inherits the properties of another class
class Transportation {
public:
int ID;
string company;
string vehicleOperator;
Transportation(int,string,string) {
}
};
class SeaTransport: public Transportation {
public:
int portNumber;
SeaTransport(int)::Transportation(int,string,string) {
}
};
I'm having issues with line 18 (SeaTransport(int)::Transportation(int,string,string)).
The error I receive occurs at the pont where I declare Transportation.
As seen in the code, a class Transportation is the body class and class SeaTransport inherits the properies of Transportation.
Transportation::Transportation(int, std::string, std::string)
+2 overloads
type name is not allowed
This error occurs at the int
typedef std::__cxx11::basic_string std::string
type name is not allowed
and this final error occurs at both string variables.
It seems you mix together scoping and a constructor initializer list.
The double-colon operator :: is for scope, while a constructor followed by a single colon and a list of initializations is an initializer list.
You must declare the SeaTransport constructor to take all the arguments, including those for the parent class (assuming you want to pass them on to the base constructor):
SeaTransport(int port, int id, string company, string operator);
Then in the definition (implementation) of the constructor you "call" the parent constructor in the constructor initializer list:
SeaTransport(int port, int id, string company, string oper)
: Transport(id, company, oper), // "Call" the parent class constructor
portNumber(port) // Initialize the own members
{
}
As Mr Some Programmer Dude said, you've a Scope problem in your code,
I will try to answer for your second question which is, how to add featured variables on your constructor.
Same as what you did for the port attribute.
You can define before all your Attribute which is boatNumber as int boadNumber = 0 then, you'll overload your
constructor with boatNumber(num) after the initializer operator and int num before the initializer operator.
class Transportation {
public:
int ID;
string company;
string vehicleOperator;
Transportation(int,string,string) {
}
~Transportation(){}
};
class SeaTransport: public Transportation {
public:
int portNumber;
int boatNumber;
SeaTransport(int num, int port, int id, string company, string oper)
:Transportation(id, company, oper), boatNumber(num),portNumber(port) {}
~SeaTransport(){}
};
But, if you want to get things more specific, you can create another class which is derived from SeaTransport
And then you'll define the number of your boat and more other details, if you want.
I'll draw you an instance of it :
class Boat: public SeaTransport {
public:
int boatNumber;
Boat(int bNum,int num, int port, int id, string company, string oper):
SeaTransport( num, port, id, company, oper),boatNumber(bNum){}
~Boat(){}
};
I haee this small piece of code in which I'm trying to create a struct Employee. The employee can be either a manager or worker. I'm having trouble accessing members of the unions. Here's my code
#include <iostream>
#include <string>
using namespace std;
struct Employee {
int id;
union Person {
struct Manager {
int level;
} manager;
struct Worker {
string department;
} worker;
} company[3];
};
int main() {
Employee one;
one.id = 101;
one.company[0].manager.level = 3;
Employee two;
two.id = 102;
two.company[1].worker.department = "Sales";
Employee three;
three.id = 103;
three.company[2].worker.department = "Marketing";
}
The error I get is
arraOfUnions.cc:13:5: error: member 'Employee::Person::Worker Employee::Person::worker' with constructor not allowed in union
arraOfUnions.cc:13:5: error: member 'Employee::Person::Worker Employee::Person::worker' with destructor not allowed in union
arraOfUnions.cc:13:5: error: member 'Employee::Person::Worker Employee::Person::worker' with copy assignment operator not allowed in union
arraOfUnions.cc:13:5: note: unrestricted unions only available with -std=c++0x or -std=gnu++0x
I'm not sure what I'm doing wrong. Please help
Thanks SO
You cannot have a non-POD object in your union, but you can have a pointer to a non PDO object (therefore string* is valid).
What are POD types in C++?
Pehaps a const char* is enough, if all you need is access to those string literals "Sales" & "Marketing"-
BTW - you data model is completely wrong. You should not be using a union you need to use a class hierarchy.
You need a base class Employee, and a derived class Manager.
struct Employee {
int id;
string department;
};
struct Manager : public Employee
{
int level;
}
and dont use struct use class
and have better naming for members. like m_company or company_
and dont do using namespace std, say std::string etc
class Employee {
int _id;
std::string _department;
};
class Manager : public Employee
{
int _level;
}
This question already has answers here:
What are the rules for calling the base class constructor?
(10 answers)
Closed 7 years ago.
Hey guys. I dont know how i suppose to do about setting values to derived classes ctor. And here is my code. I remember something like that build in my class. But i know that we can write something like that build ( xxx():yyy(){,,,};).
Check the main's second object.
#include <iostream>
using namespace std;
class vehicle
{
protected:
string brand;
int wheelNumber;
double maxSpeed=0;
public:
vehicle(){cout<<"default ctor for vehicle"<<endl;}
vehicle(string br1, int wn1, double ms1)
{brand=br1; wheelNumber=wn1; maxSpeed=ms1;}
void setbrand(string br){brand=br;}
string getbrand(string br){return brand;}
void setWN(int wn){wheelNumber=wn;}
int getWN(int wn){return wheelNumber;}
void setMaxS(double ms){maxSpeed=ms;}
double getMaxS(double ms){return maxSpeed;}
~vehicle(){cout<<"dtor for vehicle."<<endl;}
};
class car: public vehicle
{
private:
int numberOfDoors;
string fuelType;
public:
car(){cout<<"default ctor for car"<<endl;}
car(int nOD,string fT){numberOfDoors=nOD; fuelType=fT;}
void setnOD(int nOD){numberOfDoors=nOD;}
int getnOD(int nOD){return numberOfDoors;}
void setfT(string fT){fuelType=fT;}
string getfT(string fT){return fuelType;}
void printFeatures()
{
cout<<endl;
cout<<"brand:"<<brand<<endl;
cout<<"wheelNumber:"<<wheelNumber<<endl;
cout<<"MaxSpeed:"<<maxSpeed<<endl;
cout<<"NumberOfDoors:"<<numberOfDoors<<endl;
cout<<"FuelType:"<<fuelType<<endl<<endl;
}
~car(){cout<<"dtor for car."<<endl;}
};
int main()
{
car *cc;
cc= new car;
cc->setbrand("bmw");
cc->setfT("diesel");
cc->setMaxS(333.25);
cc->setWN(4);
cc->setnOD(6);
cc->printFeatures();
delete cc;
car *xx;
xx= new car;
car(5,"gasoline"):vehicle("mercedes",4,489.12);//Part that i cant figure it out.
xx->printFeatures();
delete xx;
}
The ctor(...):base(...){} syntax is used when defining the derived class constructor, not when instantiating an object. So change the constructor to car to this:
car(int nOD,string fT, string br1, int wn1, double ms1): vehicle(br1, wn1, ms1) {
numberOfDoors=nOD; fuelType=fT;
}
And instantiate your car object like this:
xx= new car(5,"gasoline", "mercedes",4,489.12);
Even better, take advantage of C++'s member-initialization syntax to define your constructors:
vehicle(string br1, int wn1, double ms1)
:brand(br1), wheelNumber(wn1), maxSpeed(ms1)
{}
// ...
car(int nOD,string fT, string br1, int wn1, double ms1)
: vehicle(br1,wn1, ms1), numberOfDoors(nOD), fuelType(fT)
{}
You need to code this into the constructor to get this to work. When you derive from a class the constructor of that derived class needs to take in the parameters for the base constructor and its own construction.
class Base
{
int foo;
public:
Base(int f) : foo(f) {};
};
class Derived : public Base
{
int bar;
public:
Derivced(int f, int b) : Base(f), bar(b) {}
^^^^^^^ ^^^^^^^^^
construct the base part constrcut the derived part
};
So for you example the constructor for car would become:
car(string br1, int wn1, double ms1, int nOD,string fT) : vehicle(br1, wn1, ms1),
numberOfDoors(nOD),
fuelType(fT) {}
Since you are allocating instance of class car which is derived class so it is calling both the ctors. First it will call the ctor of class 'vehicle' and then 'car'. [Read the order of calling ctor in case inheritance]
I am trying to access the get_workhour() function. How do I do this?
Does polymorphism only works for overriden functions?
The manager class has a special function get_workhour() which is not present in base class employee. How can we call that function when both class's objects are stored in a vector of employee type, using polymorphism?
#include <iostream>
#include <vector>
using namespace std;
class employee{
protected:
string name;
double pay;
public:
employee(){
name="xyz";
pay =0.0;
}
employee(string name,double pay) {
this->name = name;
this->pay = pay;
}
string get_name(){
return name;
}
virtual double get_pay(){
return pay;
}
};
class manager:public employee{
protected:
int workhour;
public:
manager(){
workhour = 0;
}
manager(string name,double pay,int workhour):
employee(name,pay){
this->workhour = workhour;
}
virtual int get_workhour(){
return workhour;
}
virtual double get_pay() {
return pay + 100;
}
};
int main()
{
employee emp1("vivek",1500);
manager m1("william",1300,10);
vector<employee*> emps;
emps.push_back(&m1);
emps.push_back(&emp1);
cout<<"Name of manager is : "<<emps[0]->get_name()<<endl;
cout<<"Pay for the manager is :"<<emps[0]->get_pay()<<endl;
cout<<"Workhour of manager is : "<<ptr->get_workhour()<<endl;
cout<<"Name of employee is : "<<emps[1]->get_name()<<endl;
cout<<"Pay for the employee is : "<<emps[1]->get_pay()<<endl;
return 0;
}
You can't and you shouldn't. If you want all Derived to be interacted with via Base's interface, then everything you want to do to a Derived must be represented by Base's interface.
In general C++ (and most object oriented languages) try to discourage downcasting (casting a base type to a derived type). If you absolutely need to you can use a dynamic_cast to cast an employee to a manager. But do this only if you are sure that your pointer actually refers to a manager. Without a cast you only have access to the base type's interface.
You can use the dynamic_cast as follows:
manager* m = dynamic_cast<manager*>(emps[0]);
One option is to have an empty method for get_workhour() in the base class and just have the manager class override it.