Reputation: 13000
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?
Upvotes: 5
Views: 196
Reputation: 69260
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.
Upvotes: 9
Reputation: 780
My 2 cents: split your behaviour between 2 tasks:
virtual doActive(){}; //doNothing
void setActive (bool state) {
m_active = state;
doActive();
}
Upvotes: 1
Reputation: 993183
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.
Upvotes: 6
Reputation: 206546
Basically your case is custom made for Template method design pattern.
Upvotes: 2
Reputation: 36487
How about making setActive()
non-virtual but instead adding a second virtual member (e.g. onSetActive()
)that's called by setActive()
?
Upvotes: 1