#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.
Related
I have declared a class Products and another class CD the class CD is inheriting the class Products.
Now I have declared an constructor to update the value of the. and I am getting an error
#include <iostream>
#include <string>
class Products
{
private:
std::string name;
std::string type;
double price;
public:
virtual std::string getname();
virtual double getprice();
virtual void show();
std::string gettype()
{
return type;
}
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(std::string sname,double sprice,std::string sartist,std::string sstudio)
{
this->type = "CD";
this->name = sname ;
this->price = sprice;
this->artist = sartist;
this->studio = sstudio;
}
void show()
{
std::cout<<"\nName of the CD:\t"<<this->name;
std::cout<<"\nArtist of the CD:\t"<<this->artist;
std::cout<<"\nStudio of the CD:\t"<<this->studio;
std::cout<<"\nPrice of the cd:\t"<<this->price;
}
};
int main()
{
CD obj("Oceans",49,"somesinger","somestudio");
}
ERROR :
In constructor 'CD::CD(std::string, double, std::string)';
'std::string Products::type' is private within this context
this->type="CD";
'std::string Products::name' is private within this context
this->name=sname;
'double Products::price' is private within this context
this->price= sprice;
Basically it is not giving error for the private data members of the CD class but just the data members that are being inherited from Products Class
#include <iostream>
#include <string>
class Products
{
private:
std::string m_name;
std::string m_type;
double m_price;
public:
// No need for your setters/getters to be virtual
// if the derived class won't override anything or not
const std::string& getType() const { return m_type; }
const std::string& getName() const { return m_name; }
double getPrice() const { return m_price; }
void setType(const std::string& new_type) { m_type = new_type; }
void setName(const std::string& new_name) { m_name = new_name; }
void setPrice(double new_price) { m_price = new_price; }
// Force derived class to override function
virtual void show() = 0;
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(std::string sname,double sprice,std::string sartist,std::string sstudio)
{
this->setType("CD");
this->setName(sname) ;
this->setPrice(sprice);
this->artist = sartist;
this->studio = sstudio;
}
void show()
{
std::cout<<"\nName of the CD:\t"<<this->getName();
std::cout<<"\nArtist of the CD:\t"<<this->artist;
std::cout<<"\nStudio of the CD:\t"<<this->studio;
std::cout<<"\nPrice of the cd:\t"<<this->getPrice();
}
};
int main()
{
CD obj("Oceans",49,"somesinger","somestudio");
obj.show();
}
I want you to understand some changes here. First the removal of virtual keyword. In your case the setters/getters had no need to be virtual, as they were not being overriden or didn't have a need to be based on the current example. Second, the setters/getters are setup to access the private members accordingly. We now use these functions within class CD. Also we changed the function show() to be pure virtual notice the = 0 at the end. I added a comment saying this forces derived classes to override the function. Lastly, your main wasn't doing anything so I added a obj.show() to actually print something.
In this solution, I've added a constructor for Products, and CD's constructor calls it to initialize the members that are private to Products.
I removed the virtual on getName and getPrice since these features don't change other products.
show remains virtual, and I split it into a piece in Products and a piece in CD so they each display their respective fields. This separates the printing according to where the variables are, so for example, another class derived from Products wouldn't have to reimplement printing of name and price.
#include <iostream>
#include <string>
class Products
{
private:
std::string name;
std::string type;
double price;
public:
std::string getname(); // Does not need to be virtual, as it's not overriden
double getprice(); // Also does not need to be virtual
virtual void show() const {
std::cout<<"\nName of the " << type << ":\t"<<this->name;
std::cout<<"\nPrice of the " << type << ":\t"<<this->price;
};
Products (const std::string &stype, double sprice, const std::string &sname)
: name (sname), type (stype), price (sprice) {
}
std::string gettype() const
{
return type;
}
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(const std::string &sname,double sprice, const std::string &sartist, const std::string &sstudio)
: Products ("CD", sprice, sname)
{
artist = sartist;
studio = sstudio;
}
void show() const override
{
Products::show(); // Call parent show() to show the basics
std::cout<<"\nArtist of the " << gettype() << ":\t"<<this->artist;
std::cout<<"\nStudio of the " << gettype() << ":\t"<<this->studio;
}
};
int main()
{
Products shoe ("Shoe", 3.49, "Nike runner");
shoe.show();
CD obj("Oceans",49,"somesinger","somestudio");
obj.show();
}
Having been taught Java, I am confused by how Object Orientation is implemented in C++.
Having this class:
class Car {
int weight;
public:
Car(int input) {
weight = input;
}
void sayVroem() {
std::cout << "Vroem...";
}
};
In Java I would be able to declare this an abstract class by declaring it as public abstract class Car. This would result in that the class cannot be instantiated. Is something similar possible in c++?
You need to declare at least one method pure virtual, like:
class Car {
int weight;
public:
Car(int input) {
weight = input;
}
void sayVroem() {
std::cout << "Vroem...";
}
virtual void ImAPureVirtualMethod() = 0;
};
If you have no virtual methods
class Car {
int weight;
public:
void sayVroem() {
std::cout << "Vroem...";
}
protected:
Car () = default;
};
Or by making the destructor pure virtual like
class Car {
int weight;
public:
Car(int input) {
weight = input;
}
void sayVroem() {
std::cout << "Vroem...";
}
virtual ~Car() = 0;
};
One thing to be aware of when using virtual descructors is that when a derived class is destroyed it will call the base class descructor so you will need to provide an implementation, for example:
inline Car::~Car() { }
There are plenty of stuff out there describing this:
https://en.cppreference.com/w/cpp/language/abstract_class
https://www.geeksforgeeks.org/pure-virtual-functions-and-abstract-classes/
The easiest way to do this explicitly is to declare all constructors as protected => Then you won't be able to instantiate the class even without pure virtual members.
In your case:
class Car {
int weight;
protected: // only derived classes can access those functions
Car(int input) {
weight = input;
}
// if you just have the default c-tor you can move it to protected like this:
Car() = default;
public:
void sayVroem() {
std::cout << "Vroem...";
}
// feel free to add virtual methods later on if required
};
Have you tried searching online ?
I'm not using C++ but the research seems pretty easy and with plenty of answers.
IBM Explanation of C++ abstract classes
Wikibooks - C++ Programming/Classes/Abstract Classes
I'm experimenting with the decorator design pattern in c++. However, I was not able to implement it without an abstract super-class from which both the core and decorating classes inherit.
I don't understand why abstract super-class is needed.
My working decorator example:
#include <string>
#include <iostream>
using namespace std;
// abstract superclass
class Pizza
{
public:
virtual string GetDescription() = 0;
virtual int GetCost() = 0;
};
// base class that can be extended
class Margharita: public Pizza
{
private:
string description;
int cost;
public:
Margharita(string t, int c){description = t; cost = c;}
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};
// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};
int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Margharita("Margharita", 100));
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}
that gives the output: Margharita, Extra Cheese 120.
If I remove the abstract super-class, the decoration stops working:
#include <string>
#include <iostream>
using namespace std;
// base class that can be extended
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};
// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};
int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Pizza());
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}
In this case the output only shows the attributes of the core object (Pizza 100).
Why is this happening?
When you removed the abstract base class you made the function GetDescription and GetCost not virtual. As such they aren't dispatched dynamically. Which is why pizza->GetDescription() called the Pizza member function, it was a call resolved based on the static type of pizza only.
You don't need to have an abstract base to make it work again, only dynamic dispatch, so just add the virtual specifier
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
virtual string GetDescription(){return(description);}
virtual int GetCost(){return(cost);}
};
This will allow overriding in ExtraCheese, to be picked up by dynamic dispatch. You can also help the compiler catch such mistakes by employing the override specifier. Had you defined ExtraCheese like this:
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() override { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() override { return(pizza->GetCost() + 20); }
};
A modern compiler would have complained you are trying to override a function that isn't declared virtual. The mistake would have been apparent.
I have a base class Animal and two derived classes Bird and Fish. I have two virtual functions, fly(int) and swim(int) in Animal for Bird and Fish respectively. There is a common function aliveSince() in Animal
class Animal{
public:
Animal() {
age = 0;
}
virtual ~Animal(){}
static Animal* factory(int type);
int aliveSince(){
return age;
}
virtual int fly(int m){} //error, needs a return value
virtual int swim(int m){} //error, needs a return value
private:
int age;
};
class Bird: public Animal{
public:
Bird(){
totalFlight = 0;
}
int fly(int m){
cout<<"Bird flew "<<m<<" metres\n";
return totalFlight = totalFlight+m;
}
private:
int totalFlight;
};
class Fish: public Animal{
public:
Fish(){
totalSwim = 0;
}
int swim(int m){
cout<<"Fish swam "<<m<<" metres underground\n";
return totalSwim = totalSwim + m;
}
private:
int totalSwim;
};
Animal* Animal::factory(int type){
if (type) return new Bird();
else return new Fish();
}
I want to use the these classes like this:
Animal *a = Animal::factory(1); //Bird
Animal *b = Animal::factory(0); //Fish
a->aliveSince();
b->aliveSince();
a->fly(5);
b->swim(5);
I am compiling in MS VC++ and it generates errors, Animal::fly and Animal::swim needs a return value. However, this compiles fine in GNU C++.
How can I get rid of the error without having to specify a return value in the virtual methods?
Note that I can't make these functions pure virtual as it would make the Animal class abstract and all derived classes will need to implement fly() and swim()
UPDATE: Just saw you can't use pure virtual methods because you need some default.
If you need a default, you'd better return it explicitly, instead of letting the compiler (or chance) decide the return value. So just return 0.
ORIGINAL
If you don't supply any implementation in your base class, use Pure Virtual methods. Like so:
class Animal
{
public:
virtual int fly(int m) = 0;
virtual int swim(int m) = 0;
};
A Pure-Virtual method is a method that has no body. It makes the Animal base class abstract - you will not be able to construct any instances of it, just of derived classes that implement these methods.
Both functions need to return a value, as you have guessed:
virtual int fly(int m){ return 0; }
virtual int swim(int m){ return 0; }
Either, put in return 0; in both scopes. That would be your answer 'as you are asking'.
Or try somything like this to simplify your code:
class Animal{
public:
Animal()
{
totalMoved = 0;
}
virtual ~Animal(){}
virtual int move( int m )
{
totalMoved += m;
cout<<"Total distance " << totalMoved << std::endl;
return totalMoved ;
}
protected:
int totalMoved;
};
class Bird: public Animal{
public:
int move(int m)
{
cout<<"Bird flew "<<m<<" metres\n";
return Animal::move( m );
}
};
class Fish: public Animal{
public:
int swim(int m){
cout<<"Fish swam "<<m<<" metres underground\n";
return Animal::move( m );
}
};
Specific algorithms to move can be written within the Bird and Fish class. The totalMove could be shared, so share it. That is the concept of OOP programming and leaves you out of doing things double.
Have added the console output in Animal too, so you can see what happens when.
I Have two classes:
First:
class Thing {
public:
int code;
string name;
string description;
int location;
bool canCarry;
Thing(int _code, string _name, string _desc, int _loc, bool _canCarry) {
code = _code;
name = _name;
description = _desc;
location = _loc;
canCarry = _canCarry;
}
};
Second:
class Door: public Thing {
private:
bool open;
public:
int targetLocation;
Door(int _code, string _name, string _desc, int _loc, int _targetLoc) :
Thing(_code, _name, _desc, _loc, false) {
open = false;
targetLocation = _targetLoc;
}
void Use() {
open = true;
}
void Close() {
open = false;
}
bool isOpen() {
return open;
}
};
Forget private/public atributes...
I need to store some objects of base class and some objects of derived class,
something like this:
vector < Thing*> allThings;
things.push_back(new Thing(THING1, "THING1", "some thing", LOC1, true));
things.push_back(new Door(DOOR1, "DOOR1", "some door", LOC1, LOC2));
But in this case, functions Use(), Open(), and isOpen() will not be reachable because of slicing..
Do you have some suggestions, how to store these objects together without creating new structure of vector<Thing*> and vector<Door*>??
Thanks
A good solution to a problem when you need a container of objects with polymorphic behavior is a vector of unique pointers:
std::vector<std::unique_ptr<Thing>>
There would be no slicing in this situation, but you would have to figure out when it's OK to call Use(), Open(), and isOpen().
If you can move the methods from the derived class into the base, go for it; if you cannot do that because it makes no sense for a Thing to have isOpen(), consider using a more advanced solution, such as the Visitor Pattern:
class Thing;
class Door;
struct Visitor {
virtual void visitThing(Thing &t) = 0;
virtual void visitDoor(Door &d) = 0;
};
class Thing {
...
virtual void accept(Visitor &v) {
v.visitThing(*this);
}
};
class Door : public Thing {
...
virtual void accept(Visitor &v) {
v.visitDoor(*this);
}
}
Store pointers instead of instances, and declare public and protected methods as virtual in the base class(es).