I have a base class and classes that derive from it. The base class Controllable acts as an interface for an input loop, and other classes derive from it to get a spot in that loop to get events like if a key is pressed.
class Controllable{
public:
virtual void setActive(bool state) { m_active = state; }
virtual void input(Event & e) =0;
private:
bool m_active;
};
class Button : public Controllable{
public:
void setActive(bool state){ /*do extra work*/ m_active = state; }
void input(Event & e) override;
};
Since the Button class deals with events from an event queue, setting it to inactive (which takes it out of the input loop) may cause it to miss important events like a key being unpressed, so it needs extra code to put it into a friendly inactive state should it ever become active again later.
My question, what is the best way to ensure that setActive always has the intended effect of switching m_active to the correct state, while at the same time, not requiring derived classes to define it unless they need to attach extra needed code?
Keep the setActive method non-virtual and then define a separate protected method activeChanged that the child classes can override
class Controllable{
public:
void setActive(bool state) { m_active = state; activeChanged(state); }
virtual void input(Event & e) = 0;
protected:
virtual void activeChanged(bool newState) {}
private:
bool m_active;
}
class Button : public Controllable{
protected:
void activeChanged(bool newState){ /*do extra work*/ }
public:
void input(Event & e);
};
With this approach you are keeping the external public interface separated from the internal protected interface intended for child classes.
One way to do this is to define "pre" and "post" virtual methods:
class Controllable{
public:
void setActive(bool state) {
preSetActive(m_active, state);
m_active = state;
postSetActive(m_active);
};
virtual void input(Event & e) =0;
protected:
virtual void preSetActive(bool oldState, bool newState) {}
virtual void postSetActive(bool newState) {}
private:
bool m_active;
}
Note that the setActive() method is not virtual in this technique.
Basically your case is custom made for Template method design pattern.
How about making setActive() non-virtual but instead adding a second virtual member (e.g. onSetActive())that's called by setActive()?
My 2 cents:
split your behaviour between 2 tasks:
virtual doActive(){}; //doNothing
void setActive (bool state) {
m_active = state;
doActive();
}
Related
This question already has answers here:
Can I call a base class's virtual function if I'm overriding it?
(8 answers)
Closed last year.
I'm struggling to find the right answer on below question on the internet.
I'm not a native C++ programmer and have more knowledge of OOP programming in PHP, Pascal, and JavaScript, but i can manage.
I want to create a class hierarchy to handle some tasks like displaying content on a LCD screen.
It looks like the following classes:
class base {
public:
base() { };
virtual void display() { // Need to be called first from all child objects };
virtual bool keyPress(int state) { //Need to be called first from all child objects };
};
class child : public base {
public:
child():base() {};
virtual void display() {
>> call base->display()
// do some stuff
};
virtual bool keyPress(int state) {
>> call base->keyPress(state)
// check some stuff
};
};
Most program language that i know of has some 'parent::' solution to call the inherited virtual method but i cant find anything comparable for C++.
an option that i going to use for now is:
class base {
protected:
virtual void _display() =0;
virtual bool _keyPress(int state) =0;
public:
base() { };
void display() {
// do basic stuff
_display();
};
bool keyPress(int state) {
if (!_keyPress(state)) {
// do basic stuff.
};
};
class child : public base {
protected:
virtual void _display() {
// do some stuff
};
virtual bool _keyPress(int state) {
// check some stuff
};
public:
child():base() {};
};
I do not like this method but it will work.
The right syntax is base::display():
class base {
public:
base() { };
virtual void display() { /* Need to be called first from all child objects*/ };
virtual bool keyPress(int state) { /*Need to be called first from all child objects*/ return 42; };
};
class child : public base {
public:
child():base() {};
virtual void display() {
base::display();
// do some stuff
};
virtual bool keyPress(int state) {
return base::keyPress(state);
// check some stuff
};
};
However, if it is the same in all child classes you better let base call its methods like you do it in your second code. It is not clear why you "do not like this method". It works, does what you want, and avoids lots of duplicate code and decreases chances for mistakes in the derived classes. Just note that the virtual methods need not be protected, because the derived classes are not supposed to call them directly, you can make them private: https://godbolt.org/z/1qjooKq85 (perhaps that is what you didn't like?).
There is an abstract class Entity, and other classes like Player and Enemy are inherit from it. When game detects a collision between the entities, the following method is called:
void handleCollision(Entity* ent1, Entity* ent2) {
if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Enemy*>(ent1) || dynamic_cast<Enemy*>(ent2)) {
//player <-> enemy collision
}
else if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Projectile*>(ent1) || dynamic_cast<Projectile*>(ent2)) {
//player <-> projectile collision
}
else if () {
//...
}
else if() {
//...
}
}
Each entity has unique behavior when colliding with another, which depends on the type of entity (Player, Enemy, etc), that's why I need to check every possible combination between entities as shown above. But I don't like the fact it creates a huge else if chain, where each entity is checked multiple times. Is there another way of doing it?
Trying to expand Ben Voigt's comment about multiple virtual dispatch, something along the lines of:
void handleCollision(Entity* ent1, Entity* ent2)
{
ent1->collide_with(ent2);
}
Where:
class Entity
{
public:
virtual void collide_with(Entity*) = 0; // Dispatcher
virtual void handle_collision_with(Entity*) {}
virtual void handle_collision_with(class Player*) {}
virtual void handle_collision_with(class Enemy*) {}
virtual void handle_collision_with(class Projectile*) {}
};
class Player : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Entity* other) override
{
// Unhandled entity
}
virtual void handle_collision_with(Player* other) override
{
// Handle collision player-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision player-projectile
}
};
class Enemy : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Enemy* other) override
{
// Handle collision enemy-enemy
}
virtual void handle_collision_with(Player* player) override
{
// Handle collision enemy-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision enemy-projectile
}
};
class Projectile : public Entity
{...}
source: a-polyglots-guide-to-multiple-dispatch
Use a virtual function defined in Entity class to uniquely identify the derived class whether Player or Enemy. This will be a good practice to avoid any runtime errors as well.
enum EntityType { Entity, Player, Enemy}
In the Entity class define a virtual function like this,
virtual EntityType getType (return Entity;)
and override the function in two classes accordingly.
As the title says I have the following "base" class that user can extend:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start();
virtual void EventHandler(SDL_Event event);
virtual void Update();
virtual void Draw();
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
My problem is I can't know what name, the user, choose for his classes so how I can call a known method (like Start or EventHandler) from my main class inside an unknown class?
An example of a class that is unknown to me but well-known to the user can be:
class SomeFunnyRandomName : public BaseScene
{
public:
void Start();
void Eventhandler(SDL_Event event);
void Update();
void Draw();
};
So form the main class I need to call Start() inside "SomeFunnyRandomName" without:
SomeFunnyRandomName sfrn = new SomeFunnyRandomName();
If you can include the code it will be very helpful (but not required).
You take a reference or pointer to BaseScene, and call the methods on that. The caller passes an instance of their derived class.
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene & scene) : scene(scene) {}
void doStuff() { scene.Start(); scene.Update(); }
/*... etc*/
};
int main() {
SomeFunnyRandomName scene;
UsesScene usesScene(scene);
usesScene.doStuff();
}
I was working on implementing an adapter design pattern to utilize the existing classes. My problem is, the classes works almost same, but have different names and less functionalities on another.
For example, each Work class and Homework class has one function that does the same, which is doWork() and doHomework().
I can link these to doThis() in Task interface. But, Work class doesn't have done() function while Homework class has it. How would I take care of this? Just no implementation? Are there any better approach?
class Task {
public:
virtual int doThis() = 0;
virtual bool done() = 0;
};
class Work {
public:
Work();
int doWork();
};
class Homework {
public:
Homework();
int doHomework();
bool done();
bool isDone;
};
class WorkAdapter : public Task, private Work {
public:
WorkAdapter();
int doThis() {
return doWork();
}
virtual bool done() {
// Is this okay not to implment this?
}
};
class HomeworkAdapter : public Task, private Homework {
public:
HomeworkAdapter();
int doThis() {
return doWork();
}
virtual bool done() {
return isDone;
}
};
int main() {
Task *homework = new HomeworkAdapter();
Task *work = new WorkAdapter();
homework->doThis();
bool isHomeworkDone = homework->done();
work->doThis();
bool isWorkDone = work->done(); // This would never be called in my implementation...
}
The adapter implementation using multiple inheritance (public for the target, private for the adaptee) is a valid approach.
Just take care of the the return type of the function:
class HomeworkAdapter : public Task, private Homework {
public:
HomeworkAdapter() {}
int doThis() override { // make sure you override target member
return doWork(); // and return value as expected
}
bool done() override {
return isDone;
}
};
Hint: virtual doesn't need to be specified in the derived class. Instead it's worth to use override, just to avoid subtle issues in case of non matching parameter or return types.
When no feature is available for taking care of done() in the adaptee, you must emulate it. So its's not just about changing the name, but also ensuring similar behaviour:
class WorkAdapter : public Task, private Work {
bool isdone; // functionality to add
public:
WorkAdapter() : isdone(false) {}
int doThis() override {
auto rc = doWork();
isdone = true; // once it's done, it's done ;-)
return rc;
}
bool done() override {
return isdone; // you must add this
}
};
I'm working on implementing an observer design pattern with a notification
object that I can change to suit various observed classes.
Here is the observer framework:
notify.h:
class INotification //Notification container
{
public:
virtual ~INotification()=0;
};
inline INotification::~INotification() {}
class IObserver
{
public:
virtual ~IObserver();
virtual void update(INotification*)=0;
};
inline IObserver::~IObserver() {}
class ISubject
{
public:
virtual ~ISubject();
virtual void attach(IObserver*)=0;
virtual void detach(IObserver*)=0;
virtual void notify()=0; //Note: observer deletes notifications
};
inline ISubject::~ISubject() {}
I am implementing a timer class that I want other classes to observe for timer events:
timer.h:
class ITimerObserver;
class ITimer : public ISubject
{
public:
virtual ~ITimer();
virtual void setInterval(const unsigned int,const unsigned int)=0; //Seconds, Microseconds
virtual void run()=0; //Check for triggering
virtual const timeval& now()=0;
virtual bool isItTime(const timeval&,const timeval&)=0;
};
inline ITimer::~ITimer() {}
class CTimer : public ITimer
{
protected:
std::vector<IObserver*> observers;
timeval interval; //How often we are triggering
timeval lastTrigger; //When we were last triggered
timeval current; //Our current time
private:
virtual ~CTimer();
virtual void attach(IObserver*);
virtual void detach(IObserver*);
virtual void notify();
virtual void setInterval(const unsigned int,const unsigned int); //Seconds, Microseconds
virtual void run(); //Check for triggering
virtual const timeval& now();
virtual bool isItTime(const timeval&,const timeval&);
};
class ITimerNotification : public INotification
{
public:
virtual ~ITimerNotification();
virtual const timeval& getTime()=0;
};
inline ITimerNotification::~ITimerNotification() {}
class CTimerNotification : public ITimerNotification
{
public:
CTimerNotification(const timeval& t)
{
time = t;
}
protected:
timeval time;
private:
virtual ~CTimerNotification();
virtual const timeval& getTime()
{
return time;
}
};
class ITimerObserver : public IObserver
{
public:
virtual void update(ITimerNotification*)=0;
};
So I want to be able to pass a more specific Notification object (A TimerNotification) whenever a timer event happens, so that I can call a specific update() function on the observer, so I made a new Observer class (ITimerObserver).
Here is the function that notifies the observer on a timer event:
void CTimer::notify()
{
std::vector<IObserver*>::iterator it;
for(it=observers.begin();it!=observers.end();++it)
{
ITimerNotification* notification = new CTimerNotification(now());
(*it)->update(notification);
}
}
Here is the actual observer itself:
class TestObserver : public ITimerObserver
{
public:
virtual void update(INotification* note)
{
std::cout<<"???: TestObserver: update()!\n";
}
virtual void update(ITimerNotification* note)
{
std::cout<< note->getTime().tv_sec << "." << note->getTime().tv_usec <<": TestObserver: update()!\n";
}
};
When run, the program runs the interface method, void update(INotification) instead of the more specific ITimerNotification as I would expect. The trouble is, how do I get the CTimer class to know about the TimerObserver without breaking the interface contract that says it only takes a Base Observer pointer?
To answer the first part of the question:
ITimerNotification* notification = new CTimerNotification(now());
(*it)->update(notification);
This code passes notification to an IObserver::update method, of which there is only one:
virtual void update(INotification*)=0;
Hence the call to that virtual method in TestObserver.
For the second part, you need to recognise that you wish the call to in a sense be virtual on two types, the observer and notification. This is known as double dispatch, and requires some work in C++.
The key point to understand is the static and run-time binding of the function calls. At the calling point, for example:
(*it)->update(notification);
the compiler can only do static resolution of the names of functions. Where these are virtual calls, there will be run-time binding to the actual method based on the type of object the method is being called on (not the parameter). So in order to do double dispatch through built-in mechanisms, you need to call a virtual method on both the notification and the observer.
See for example:
Multiple dispatch in C++
How does double dispatch work in Visitor pattern?
This topic is also covered in great detail in one of the Meyer's books (I forget which.)