The usual example with a unit.
class Unit {
private:
int health;
public:
Unit(int health);
virtual ~Unit();
protected:
virtual void setHealth(int newHealth);
}
next, make heir
class Healer : public Unit {
public:
Healer(int health);
virtual void healing(Unit* other);
};
In the implementation of healing
void Healer::healing(Unit* other) {
other->setHealth(100);
}
encapsulation does not allow doing so other-> setHealth (100);
'setHealth' is a protected member of 'Unit' other->setHealth(newHealth);
can only access this member on an object of type 'Healer' virtual void
setHealth(int newHealth);
In this case, you can call this method for "this".
P.S.: public method setHealth - do not offer. method healing for class Unit - do not offer.
As mentioned by #EekTheCat, you could use a friend.
Alternatively, you could add a function to receive health. You currently have a public function for setting health. You can just as easily add a public function for receiving health:
class Unit {
private:
int health;
public:
Unit(int health);
virtual ~Unit();
protected:
virtual void setHealth(int newHealth);
void acceptHealth();
}
void Unit::acceptHealth() {
health += 100;
}
You could create a new child class called the patient and implement the accept health as a virtual function of Unit, implemented by the patient class.
Your code is not complicated (thank you for keeping it minimal), but you could add tokens and security to pass around to ensure that health points are properly conserved according to rules that could be enforced in your virtual reality.
Related
I am trying to design a parking system (Low-level Design )
Some classes behave like this.
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual void leaveParking(Vehicle*);
virtual int getChargePerHr();
//virtual void getChargePerHr() = 0;
Vehicle() {}
};
class Car : public Vehicle
{
private :
int chargePerHr = 30;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Car(){}
};
class Bike : public Vehicle
{
private :
int chargePerHr = 10;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Bike(){}
}
void Vehicle ::leaveParking(Vehicle* v)
{
int pay = v-> // Here expecting Car class member function getChargePerHr() should come
//so that I can access private member chargePerHr of car class.
// But I am not able to access the Car class member function here.
}
int main()
{
Car c1; // assume Car c1 has already parked.
Vehicle v;
Vehicle* vptr = new Vehicle();
vptr = new Car();
c1.leaveParking(vptr); // Car c1 wants to leave the parking place
}
I want to access getChargePerHr() of Car class using Base class Vehicle member function.
I tried with pure virtual function but still could not make it.
Could anyone help me?
Problem
Here:
void Vehicle::leaveParking(Vehicle* v)
{
...
}
You're not able to access Car::getChargePerHr() because v is a Vehicle not a Car.
Clearly you're attempting to achieve polymorphism since it appears you want derived classes of Vehicle to perform the same actions when they leave parking.
Solution
Declare Vehicle::getChargePerHr() as pure virtual (or virtual if you want a default implementation)
Provide implementations of getChargePerHr() in your derived classes
Implement Vehicle::leaveParking() using just the methods you've defined in Vehicle
At runtime, the virtual table will resolve overrides and call the correct derived implementation.
Other Issues
You are inheriting from Vehicle without declaring its destructor virtual. This means if any child classes need to perform clean-up, their destructors won't be called.
You're missing a semicolon after the Bike class declaration.
If every Vehicle does the same thing when leaving parking, it doesn't make sense to have leaveParking() be virtual—you make a member function virtual if you want it to be able to be overridden by child classes.
Vehicle::leaveParking() should probably not be taking another Vehicle as a parameter. The function acts on the vehicle itself, not on a different one.
If your constructor is empty, it's better to leave it out of the class declaration since it can confuse others who might read your code.
And many more issues. I suggest you take aalimian's advice to read up on C/C++. Your code shows many misunderstandings.
Code
Putting everything together, here's an example:
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual ~Vehicle() = default;
void leaveParking();
virtual int getChargePerHr() = 0;
};
void Vehicle::leaveParking()
{
// This will call a derived class's implementation
int pay = getChargePerHr();
// Do more vehicle stuff
}
class Car : public Vehicle
{
private:
int chargePerHr = 30;
public:
int getChargePerHr() override;
};
int Car::getChargePerHr()
{
return chargePerHr;
}
class Bike : public Vehicle
{
private:
int chargePerHr = 10;
public:
int getChargePerHr() override;
};
int Bike::getChargePerHr()
{
return chargePerHr;
}
You can see this in action here.
Following is a simplified header file detailing three Classes. I want to be able to keep the pointer in my "Game" class private, and allow Introduction to modify it. However, as is, this is not working. As Introduction is a derivative of GameState, I thought I would be able to modify this pointer? Examples had shown that this was possible. I don't really want to move this to the Public space within Game.
class Introduction;
class Game;
class GameState;
class GameState
{
public:
static Introduction intro;
virtual ~GameState();
virtual void handleinput(Game& game, int arbitary);
virtual void update(Game& game);
};
class Introduction : public GameState
{
public:
Introduction();
virtual void handleinput(Game& game, int arbitary);
virtual void update(Game& game);
};
class Game
{
public:
Game();
~Game();
virtual void handleinput(int arbitary);
virtual void update();
private:
GameState* state_;
};
The example I was following was here...http://gameprogrammingpatterns.com/state.html
EDIT: I am wanting to do something like this...
void Introduction::handleinput(Game& game, int arbitary)
{
if (arbitary == 1)
std::cout << "switching to playing state" << std::endl;
game.state_ = &GameState::play;
}
EDIT: Thank you for the responses, I think getters and setters are the way to go. And I apologise that the problem was not clear. The problem was that I did not understand the implementation I was trying to follow. I still don't understand it, but clearly there are ways to accomplish the same thing.
I see two possible solutions.
Using Friend class
You can declare friend classes in your Game class.
Something like:
class Game {
public:
// ...
private:
// ...
friend class Introduction;
};
In this way, the class Introduction will be able to access to private member of Game class and modify it.
Getters And Setters
If you want to preserve data hiding principle, you can just provide a public member in order to modify the state of your game.
Here, an example:
class Game {
public:
void setNewState(GameState* setter) noexcept;
const GameState* getCurrentState() const noexcept;
// ...
};
How about a getter and an setter?
class Game
{
public:
....
GameState * getGameState() const { return state_; }
void setGameState(GameState * newState) { state_ = newState; }
....
private:
GameState* state_;
}
You can make the pointer Protected and make Game a friend to GameState, to allow Game to access protected members in GameState.
But as the above comments indicate, its not really clear what you are actually asking.
i want to understand the behavior of pure virtual functions in derived class when passing to it an argument of same type as (abstract) base class.
to clarify the question, i took the following code from GeeksForGeeks and modified it:
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary(const Employee&) = 0;
{ /* common raise salary code */ }
virtual void promote(const Employee&) = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary(const Employee&)
{ /* Manager specific raise salary code, may contain
increment of manager specific incentives*/ }
virtual void promote(const Employee&)
{ /* Manager specific promote */ }
};
}
Now, how can we get access to the field degree in derived class Manager inorder to update his degree? since the passed argument to raiseSalary(Employee& employee) could be Manager or Engineer
I think there are two ways to handle that problem. Let's start with some really bad solution: using casting. In that case dynamic_cast. You can try to down cast a type. If dynamic_cast isn't able to do that it is going to return a null pointer or throw an exception (depends on wheather you cast a pointer or a value/reference type). But that approach is going to force you to adapt your casts as more Manager, Engineer types are going to come. You might also need to use friend to allow specific classes to access internals of others. friend is not going to be inherited in the hierarchy, so you are going to end up with many friends => broken, broken, broken :(
An alternative would be to use the Visitor Pattern: http://en.wikipedia.org/wiki/Visitor_pattern
Using the visitor pattern you can also make a base no-op visitor and finer grained Visitors to handle specific stuff. Just a small example (with specific visitors without derivation):
namespace example {
class SalaryRaisingVisitor;
class EmployeePromotingVisitor;
class Employee
{
public:
Employee() {}
//don't forget to implement the copy constructor: read more about rule of 3!!!
virtual ~Employee {}
virtual void accept(SalaryRaisingVisitor const&) = 0;
virtual void accept(EmployeePromotingVisitor const&) = 0;
};
class Manager: public Employee {
private:
int degree;
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this, degree);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this, degree);
}
};
class Engineer: public Employee {
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this);
}
};
class SalaryRaisingVisitor
{
void visit(Manager& m, int& degree) //might be const if no internal state changes
{
//...
}
void visit(Engineer& e) //might be const if no internal state changes
{
//...
}
};
}
At the end as you deal with C++, try to avoid virtual functions :) and move everything to static polymorphism :)
You are getting the concept of virtual functions with classes wrong. The class "knows" what it is (via vtable), so you can just write it as class function, not as static global function. Each function inside the class knows all class variables, so you don't have to pass an object of the class.
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary() = 0;
{ /* common raise salary code */ }
virtual void promote() = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary()
{
//the Employed standard code
Employee::raiseSalary(); //This won't compile since you set the virtual function = 0
//Manager specific raise salary code
degree = 0; //this lazy bastards should do real work like coding stuff
}
virtual void promote()
{
Employee::promote(); //employee common code. This won't compile since you set the virtual function = 0
/* Manager specific promote */
degree = degree * 2;
}
};
Employee array[10];
array[0] = Manager(); //create a manager object on the stack
array[1] = Manager(); //create a manager object on the stack
array[0].raiseSalary(); //Only Mananer0 gets raiseSalary
/*the manager object in array[0] uses its virtual function
to the manager raiseSalary function. The Manager RaiseSalary function
in this case calls the base class raiseSalary function explicitly
via Employee::raiseSalary(); */
You should rather structure your code like this:
class Employee
{
virtual void raiseSalary() = 0;
virtual void promote() = 0;
};
class Manager: public Employee
{
virtual void raiseSalary()
{ /* Manager specific raise salary code, may contain... */ }
virtual void promote()
{ /* Manager specific promote */ }
};
int main()
{
Manager bob;
bob.promote(); // <--- Proper method in the Manager class will be called.
// Current instance will always have the right class.
}
In other words you should seek opportunity to pass the specific derived class as the this parameter. Unfortunately this will not work in complex cases when multiple params are needed. But well, this was the idea of the language designers. The perfect language is not developed yet.
I think that you can't and it's the wanted behaviour.
The only way to do this is to cast you argument (which is quite complicated in C++ since you have four different kind of casting). Other solution is to give to any employee a grade attribute.
Alexis.
I will start with my design:
class IOutputBlock{
public:
virtual void write(char *) = 0;
virtual bool hasMemory() = 0;
virtual void openToWrite() = 0;
};
class IInputBlock{
public:
virtual bool hasNext() = 0;
virtual IField *next() = 0;
virtual void openToRead() = 0;
};
class MultiplicationNode : public OperationNode
{
public:
MultiplicationNode(Node *l, Node *r);
~MultiplicationNode(void);
virtual bool hasNext();
IInputBlock * evaluate();
};
class IOBlock: public IInputBlock, public IOutputBlock{
virtual void write(char *);
virtual bool hasMemory();
virtual void openToWrite();
virtual bool hasNext();
virtual IField *next();
virtual void openToRead();
};
Inside the evaluate method i need to create an IOuputBlock to write data in the block.
I want the MultiplicationNode consumer just see method for iterate over the block (IInputBlock interface).
But in the return of evaluate method, I have to perform a typecast.
Is this implementation correct? Or is it an example of bad design?
Can u suggest another design? Or maybe design pattern to help.
IInputBlock * MultiplicationNode::evaluate()
{
IOutputBlock *outputBlock = new IOBlock();
//need to write to outputblock
return (IInputBlock *)outputBlock;
}
I could also do this below, but I don't think it is right, because i was violation "program to an interface", and exposing unnecessary methods inside evaluate method from IInputBlock interface.
IInputBlock * MultiplicationNode::evaluate()
{
IOBlock *outputBlock = new IOBlock();
//need to write to outputblock
return outputBlock;
}
One option is to separate read and write classes (even if underlying data is shared):
class WriteOnlyBlock: public IOutputBlock{
// return new instance of something like ReadOnlyBlock
// potentially tied to same internal data
public: IInputBlock AsRead()...
}
This way you make conversion explicit and prevent callers from attempting to cast IInputBlock to IOutputBlock and minimize number of extra methods exposed by each class.
Here is the way I have my base class working:
class AguiWidgetBase
{
//variables
AguiDockingEnum dockingStyle;
std::string text;
AguiRectangle clientRectangle;
AguiColor tintColor;
AguiColor fontColor;
std::map<int,int,CmpIntInt> children;
//private methods
void zeroMemory();
virtual void onPaint();
virtual void onAddChildControl(AguiWidgetBase *control);
virtual void onTintColorChanged(AguiColor color);
virtual void onDockingStyleChanged(AguiDockingEnum style);
virtual void onTextChanged(std::string text);
virtual void onThemeChanged(const AguiTheme &theme);
void (*onPaintCallback)(AguiRectangle clientRect);
void (*onTintColorChangedCallback)();
void (*onDockingStyleChangedCallback)();
void (*onTextChangedCallback)();
void (*onThemeChangedCallback)();
protected:
AguiWidgetBase *parentWidget;
public:
AguiWidgetBase(void);
~AguiWidgetBase(void);
void addChildControl(AguiWidgetBase *control);
void removeChildControl(AguiWidgetBase *control);
AguiWidgetBase* getParent();
void paint();
void setTintColor(AguiColor color);
AguiColor getTintColor();
void setDockingStyle(AguiDockingEnum style);
AguiDockingEnum getDockingStyle();
void setText(std::string text);
std::string getText();
void SetTheme( const AguiTheme &theme);
};
Some of them work like this. There is a regular non-overridable funcion which calls the virtual function and the function pointer if its not NULL.
Will my virtual functions be able to once again go into the private scope when I create derived classes or must they be public?
I want to avoid them being public due to my design.
Thanks
Virtual functions can have public, protected, or private access.
A discussion of them via the C++ FAQ.
Should I use protected virtuals instead of public virtuals?
When should someone use private virtuals?
They can be private and do not need to be public.
Though they can be public, it is not considered as good design principle as Herb Sutter says.
virtual functions can be private. This is because private means that the function cannot be called by derived classes. It does not prevent the entry to the v-table being overwritten. This means that the both the base class and the derived class will have access to the overwritten virtual function.