C++ multiple inheritance - c++

Please don't question the really odd hierarchy of workers in this code here, I have no idea why anyone would want something like this, but I decided to give myself an exercise in Multiple Inheritance, just to be sure I fully understood it. So here's the result.
using namespace std;
class Employee
{
protected:
string name;
public:
string getname()
{
return name;
}
void setname(string name2)
{
name = name2;
}
Employee(string name2)
{
name = name2;
}
Employee(){}
};
class Manager : public Employee
{
public:
string getname()
{
return ("Manager" + name);
}
Manager(string name2) : Employee(name2){}
Manager() : Employee(){}
};
class Supervisor : public Manager,public Employee
{
public:
Supervisor(string name2) : Manager(name2) , Employee(name2){}
Supervisor() : Manager() , Employee(){}
string getname()
{
return ("Supervisor" + Employee::getname());
}
};
Hopefully you're understanding what I'm trying to do here. I'm getting something about an "ambiguous conversion between derived class 'Supervisor' and base class 'Employee.'" So what do I do?

Actually, the way you have defined Supervisor class, its object will have two subjects of type Employee, each coming from it base classes. That is causing problem.
The solution is to use virtual inheritance (assuming you need multiple inheritance) as:
class Manager : public virtual Employee
Hope you note the virtual keyword here. :-)

Everybody has already covered virtual inheritance, but I'd suggest reading the C++ FAQ as well.
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html

You need a virtual inheritance in this case:
#include <iostream>
#include <string>
using namespace std;
class Employee
{
protected:
string name;
public:
string getname()
{
return name;
}
void setname(string name2)
{
name = name2;
}
Employee(string name2)
{
name = name2;
}
Employee(){}
};
class Manager : public virtual Employee
{
public:
string getname()
{
return ("Manager" + name);
}
Manager(string name2) : Employee(name2){}
Manager() : Employee(){}
};
class Supervisor : public Manager,public virtual Employee
{
public:
Supervisor(string name2) : Manager(name2) , Employee(name2){}
Supervisor() : Manager() , Employee(){}
string getname()
{
return ("Supervisor" + Employee::getname());
}
};
This problem is also known as Diamond inheritance problem:
http://en.wikipedia.org/wiki/Diamond_problem

Supervisor contains two objects of type Employee, the direct one and the one over Manager. It is ambiguous to call Employee methods on a Supervisor in consequence (which Employee should be called?). You might want to employ virtual multiple inheritance instead.

Related

Using polymorphism to copy derived class' value to the base class

English is not my first language. I hope I will not make lot of mistakes. I'll try my best to be as clear as possible!
I have a base class
class engine
{
private :
std::string name;
double weight;
public:
engine();
~engine();
std::string getName() const;
int getWeight() const
};
std::string engine::getName() const{
return this->name;
}
int engine::getWeight() const{
return this->weight;
}
and derived class
class diesel : public engine
{
private:
std::string name;
double weight;
public:
diesel();
~diesel();
};
diesel::diesel(){
this->name = Diesel;
this->weight = 500.00;
}
In my main.cpp
int main()
{
diesel diesel_engine;
const engine &e = diesel_engine;
std::cout<<e.getWeight()<<e.getName()<<std::endl;
return 0;
}
1- I must construct a diesel class named diesel_engine.
2- pass diesel_engine's value to a new engine by reference??
When I call const engine &e = diesel_engine;, diesel_engine's value(name and weight) should be copied to the new engine e.
So 'e' should have weight of 500.00 and the name "Diesel".
I don't get how can I use polymorphism to do that.
Thank you for reading this question!
Lets start with the class declarations
class Engine
{
private:
float weight_;
std::string name_;
public:
Engine(float weight, std::string name) : weight_(weight), name_(name){};
std::string GetName() const { return name_;}
};
class Diesel : public Engine
{
public:
Diesel(float weight, std::string name) : Engine(weight, name){}
};
So what we have here is an Engine class which is our base class and then we define our Diesel class, Diesel inherits from Engine and passes the arguments to its base class.
Now to use this:
Diesel disel_engine(0.0, "diesel engine");
const Engine& eng = disel_engine;
cout << eng.GetName();
The call to eng.GetName() prints the correct engine name
Demo Here

Dynamic Polymorphism Error in code C++

#include <iostream>
#include <string>
using namespace std;
class Employee
{
public :
virtual int calculateSalary()= 0;
virtual string getName()=0;
virtual string getEngineer()=0; //error
virtual string getManager()=0; /error
virtual string getDirector()=0; /error
};
class Engineer: public Employee
{
protected:
string name;
int salary;
public:
Engineer(string n,int s):name(n),salary(s){ cout<<endl<<"Engineer Created"; }
~Engineer(){cout<<endl<<"engineer destroyed";}
int calculateSalary()
{
return salary * 2;
}
string getName()
{
return name;
}
string getEngineer()
{
return "Engineer";
}
};
class Manager:public Engineer
{
public:
Manager(string n,int s): Engineer(n,s) { cout<<endl<<"Manager Created"; }
~Manager(){cout<<endl<<"MANAGER destroyed";}
int calculateSalary()
{
return salary * 3;
}
string getName()
{
return name;
}
string getManager()
{
return "manager";
}
};
class Director:public Manager
{
public:
Director(string n,int s): Manager(n,s) { cout<<endl<<"Director Created"; }
~Director(){cout<<endl<<"Director destroyed";}
int calculateSalary()
{
return salary * 4;
}
string getName()
{
return name;
}
string getDirector()
{
return "director";
}
};
int main()
{
Engineer e1("rohit",20000),e2("soham",21000);
Manager m1("shyam",23000),m2("ram",23500);
Director d1("rahul",25000);
Employee *staff[] = {&e1,&e2,&m1,&m2,&d1};
for(int i=0;i<5;i++)
{
cout<<endl<<"Name : "<<staff[i]->getName() << "\t" << "Salary : " << staff[i]->calculateSalary();
}
cout<<endl<<staff[0]->getEngineer(); //error
cout<<endl<<staff[1]->getEngineer(); //error
cout<<endl<<staff[2]->getManager(); //error
cout<<endl<<staff[3]->getManager(); //error
cout<<endl<<staff[4]->getDirector(); //error
return 0;
}
/The lines with error are showing errors if i compile this code.
i want to know if it is possible to access the getEngineer(),getManager(),getDirector() via the staff pointer.
If yes, then how?
If not, then why?
and is there any alternative to access those functions keeping the data type of staff as it is(i.e Employee) ?/
All derived class from Employee must to implement all pure virtual methods, otherwise they cannot be instanced.
Why does this happen?
A derivative class inherits all methods (and member variables) from the base class.
In you case, base class has some pure virtual methods, and so the sub-classes (Engineer, Manager and Director) as well. A no-abstract class cannot have a pure virtual method, so in order to instantiate those classes, each of them should implement getEngineer() getManager() getDirector() methods.
What is the solution?
The problem in your case is a bad design decision.
The base class should represent a uniform interface for all derivative classes.
That's why, the base class Employee should not have method like getEngineer() which is a more specific information.
IMO, a better design decision (just looking at your code) could be:
class Employee {
public :
virtual int calculateSalary() = 0;
virtual string getName() = 0;
virtual string getTypeWork() = 0;
};
In that way (exploiting polymorphism property) each derivative class can correctly return a string representing its role job.
it is possible to access the getEngineer(),getManager(),getDirector() via the staff pointer. If yes, then how?
Yes, you can. However, as #Biagio Festa said you can't have pure virtual functions in your base class Employee without implementing them in your derived ones. So one solution could be having default implementations for those functions in your base class
class Employee
{
public :
virtual int calculateSalary()= 0;
virtual string getName()=0;
virtual string getEngineer() { return std::string(); }
virtual string getManager() { return std::string(); }
virtual string getDirector() { return std::string(); }
};
Then, you can override those functions in your derived classes only when needed like you did in your example.

C++ unable to use super class' methods?

I feel stupid right now, haven't been doing C++ in ages, can't understand what's wrong... However I got this following class:
#include <string>
class NamedObject
{
public:
NamedObject();
virtual ~NamedObject();
virtual std::string getName() const { return m_name };
virtual void setName(const std::string name) { m_name = name };
private:
std::string m_name;
};
And now I'm inheriting a simple class out of it:
#include "NamedObject.h"
enum eTeam { eAttacker, eDefender, eSpectator, eNone };
class Player : public NamedObject
{
public:
Player();
virtual ~Player();
virtual void printName();
virtual eTeam getTeam() const { return m_team };
virtual void setTeam(const eTeam team) { m_team = team };
private:
std::string m_name;
eTeam m_team;
};
However, I am unable to use player->setName("blabla") from my main.cpp? Here's the main file:
#include "Player.h"
int main()
{
Player* p1 = new Player();
p1->setName("Name Changed!")
p1->printName(); // prints "Unnamed" since I declared that in default ctor
return 0;
}
I'm not getting any errors, everything runs up well, the name just doesn't simply change. Also, I got all of the constructors and destructors, as well as my printName-method working perfectly, and the problem is not within them.
What you see is that setName modifies the m_name in the parent class and printName prints out the m_name of the derived class because you're redeclaring std::string m_name; in the derived class.
Remove the declaration from the derived class and mark m_name as protected member in the parent class:
#include <string>
class NamedObject
{
public:
NamedObject();
virtual ~NamedObject();
virtual std::string getName() const { return m_name };
virtual void setName(const std::string name) { m_name = name };
protected:
std::string m_name;
};
You could also keep m_name private and use the method getName() instead, as suggested by moswald.
You created another different variable m_name in your derived class that shadowed the one in the parent class.
I can see that must not be your real code.
Your derived/super class is redeclaring m_name. Probably not what you mean to do;)

c++: What is a good refactor for a duplicate member field in the subclass of a multiply-inherited class?

Title edits that reflect a better summary of the question are welcome.
I'd like to refactor these three classes somehow to remove the duplicate field represented in class C (see hierarchy). I thought about pulling the field up into a parent class, but the issue is that A and B are not similar enough to be considered "is-a", C is considered both, and it is literally only one member field so creating a class just to hold ONE THING seems a bit overkill.
Hierarchy:
(abstract data type)
class A : public O {
public:
//...
std::string GetName();
std::string GetName() const;
void SetName(std::string name);
//...
protected:
//...
std::string _name;
//...
};
//Methods and fields shown here represent the exact same representative data as in A but the classes are so dissimilar as to not be considered "is-a" relationship.
(abstract data type)
class B {
public:
//...
std::string GetName();
std::string GetName() const;
void SetName(std::string name);
//...
protected:
//...
std::string _name;
//...
};
(concrete)
class C : public A, public B {
public:
//...
C(/*..Other parameters..*/, std::string name, /*....*/)
: A(name, /*...*/), B(name, /*...*/) {
/*...*/
}
//...
private:
//...
};
You can either leave it as-is, as said previously or you can consider using composition over inheritance for class C like:
class C : public A
{
public:
// ...
// The GetName and SetName methods are inherited from A.
private:
B* b;
};
or
class C
{
public:
// ...
std::string GetName();
std::string GetName() const;
void SetName(std::string name);
private:
A* a;
B* b;
};
Looking at this question and answers: Get rid of ugly if statements clearly shows that, as #Andre mentioned, your current code is perfectly acceptable and trying to "fix" it may cause same pain and mind blow.
Leave it AS-IS, it's good.
Since C is passing in the same name parameter to both A and B, you might be able to get what you want with virtual inheritance. V below is defined to be a common base class for A, B, and C, but with virtual inheritance, they all share the same instance.
class V {
public:
std::string GetName();
std::string GetName() const;
void SetName(std::string name);
protected:
std::string _name;
V () {}
V (std::string n) : _name(n) {}
~V () {}
};
class A : virtual public V, public O {
//...
};
class B : virtual public V {
//...
};
class C : virtual public V, public A, public B {
public:
C (/*...otherargs,*/std::string name/*,moreargs...*/)
: V(name), A(/*...*/), B(/*...*/) {
//...
}
//...
};

Multiple class inheritance?

Based on the figure below, I wrote my code.
This is the code I wrote:
#include<iostream>
#include<string>
using namespace std;
class person
{
private:
int code;
string name;
public:
void setCode(int c) { code=c; }
int getCode() { return code; }
void setName(string s) { name=s; }
string getName() { return name; }
};
class account : public person
{
private:
double pay;
public:
void setPay(double p) { pay=p; }
double getPay() { return pay; }
};
class admin : public person
{
private:
string experience;
public:
void setExper(string e) { experience=e; }
string getExper() { return experience; }
};
class master : public account, public admin
{
};
int main()
{
master mastObj;// create master object.
mastObj.setName("John");
system("pause");//to pause console screen, remove it if u r in linux
return 0;
}
The compiler showed these errors:
Error 1 error C2385: ambiguous access of 'setName'
Error 2 error C3861: 'setName': identifier not found
Error 3 IntelliSense: "master::setName" is ambiguous
It is classic example of Diamond Problem in C++ when you use multiple inheritance.
The solution is : Virtual inheritance
That is, you should do this:
class account : public virtual person
{ //^^^^^^^note this
//code
};
class admin : public virtual person
{ //^^^^^^^note this
//code
};
I just found really good posts on this site, so I would redirect you to those answers here:
Virtual inheritance in C++
Virtual Inheritance Confusion
Virtual inheritance in C++
In C++, what is a virtual base class?
which also means, this topic should be voted for close.
You need virtual inheritance:
class account: public virtual person{
....
}
class admin: public virtual person{
...
}
PS And your pay, code fields lack initialization! This could lead to embarassing errors (like paying the cleaner several million of dollars :)):
#include<iostream>
#include<string>
using namespace std;
class person
{
// ...
person() : code(0), name("anonymous") {}
};
class account : public virtual person
{
// ...
account() : pay(0) {}
};
class admin : public virtual person
{
// ...
admin() : experience("unknown") {}
};
you may use mastObj.master::admin::person::setName("John");