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();
}
Related
class Entity {
public:
virtual void applyCollisionBehaviorTo(Entity &entity) { }
virtual void onCollision(Entity &entity) { }
};
class Ball : public Entity {
public:
void applyCollisionBehaviorTo(Entity entity) override {
}
void onCollision(Entity entity) override {
entity.applyCollisionBehaviorTo(this); // error: no matching function for call to 'Entity::applyCollisionBehaviorTo(Ball*)'
}
};
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
I come from a C# background so I'm getting my head around C++ inheritance and polymorphism.
Your class Entity should be like this:
class Entity
{
public:
virtual void applyCollisionBehaviorTo(Entity &entity) = 0;
virtual void onCollision(Entity &collidingEntity) = 0;
};
You can't refere to object of Ball class inside Entity, in fact entities don't even know about the existence of balls.
OTOH balls "know" that they are entities
I am making a program that solves a number of similar problems.
I am starting with a class that looks like (for example):
class problem {
void init();
void solve();
int print_result();
}
but then I would like to extend this class to different problems:
class problem_A : problem {
void init();
void solve();
void print_result();
}
class problem_B : problem {
void init();
void solve();
void print_result();
}
...
But in the main interface I would like to have a single object for either of the problems (A, B, ...) and handle them like:
obj.init();
obj.solve();
obj.print_result();
How do I achieve this? What type should obj be?
If you always want to call init() then solve() then print_result(), it's best to wrap this up in the (for C++) awkwardly named Template Method Pattern:
class problem {
public:
virtual ~problem() = default;
void run() {
init();
solve();
print_result();
}
protected:
virtual void init() = 0;
virtual void solve() = 0;
virtual void print_result() = 0;
};
And then each of your explicit problems just have to provide implementations for those functions:
class problem_A : public problem {
protected:
void init() override { .. }
void solve() override { .. }
void print_result() override { .. }
};
problem* p = new problem_A(..);
p->run(); // inits, solves, and prints the results for problem A
You stick with your original class, but make the methods pure virtual
class problem {
virtual void init() = 0;
virtual void solve() = 0;
virtual int print_result() = 0;
}
Then you can override these functions in the derived classes
class problem_A : problem {
virtual void init() override;
virtual void solve() override;
virtual void print_result() override;
}
Then you can make your object as follows:
problem* obj = new problem_A;
obj->init();
obj->solve();
obj->print_result();
This will invoke problem_A's methods, but you can use a pointer to the base class problem. Obviously make sure you clean up the memory
delete obj;
Or use smart pointers
std::unique_ptr<problem> = std::unique_ptr<problem>(new problem_A);
I get the following compilation error here. Why can't the derived class access another derived class method. Although the method is public. I am confused here. Please help.
/export/home/joshis1/Dropbox/Design_Patterns_UML/ObserverPattern/ObserverPatternProgram-build-desktop-Qt_4_8_4_in_PATH__System__Release/../ObserverPatternProgram/UpdateReceiver.h:43:
error: no matching function for call to
‘IPublisher::registerObserver(UpdateReceiver* const)’
I have a publisher class - Interface -
class ISubscriber;
/** Interface **/
class IPublisher
{
public:
virtual void registerObserver(ISubscriber *observer) = 0;
virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void notifyObserver() = 0;
virtual void setBaudRate(int newBaudRate) = 0;
virtual void setAspectRatio(int newAspectRatio) = 0;
virtual void setVolumeLevel(int newVolume) = 0;
};
//////////////////////////////////////
class ISubscriber;
class UpdateManager: public IPublisher
{
private:
QList<ISubscriber *> subscribers;
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
public:
UpdateManager()
{
qDebug()<<"Update Manager --- Server/Subject Initialized";
subscribers.clear();
}
virtual void registerObserver(ISubscriber *observer)
{
subscribers.append(observer);
}
virtual void unregisterObserver(ISubscriber *observer)
{
int index = subscribers.indexOf(observer);
subscribers.removeAt(index);
qWarning()<<"Removed the subscriber Index = "<<index;
}
virtual void setBaudRate(int newBaudRate)
{
m_baudRate = newBaudRate;
notifyObserver();
}
virtual void setAspectRatio(int newAspectRatio)
{
m_aspectRatio = newAspectRatio;
notifyObserver();
}
virtual void setVolumeLevel(int newVolume)
{
m_volumeLevel = newVolume;
notifyObserver();
}
virtual void notifyObserver()
{
#if 0
foreach( ISubscriber observer, subscribers )
{
observer.update(m_baudRate,m_aspectRatio,m_volumeLevel);
}
#endif
}
};
///////////////////
I have the observer --
/** Subscriber Interface **/
class ISubsrciber
{
public:
virtual void update(int baudRate, int AspectRatio, int VolumeLevel) = 0;
};
class UpdateManager;
class ISubsrciber;
#include "IPublisher.h"
class UpdateReceiver: public ISubsrciber
{
private:
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
int m_receiverNumber;
public:
// static int updateReceiverTracker;
/** Update Interface of the client **/
void update(int baudRate, int AspectRatio, int VolumeLevel)
{
m_baudRate = baudRate;
m_aspectRatio = AspectRatio;
m_volumeLevel = VolumeLevel;
qDebug()<<"The following client number : "<< m_receiverNumber<< " got the update ";
qDebug()<<"The baudRate is "<<baudRate;
qDebug()<<"The AspectRatio is"<<AspectRatio;
qDebug()<<"The VolumeLevel is"<<VolumeLevel;
}
/** Constructor -- and registers with the Server or Publisher or UpdateManager **/
UpdateReceiver(IPublisher *updateManager)
{
//m_receiverNumber = UpdateReceiver::updateReceiverTracker++;
updateManager->registerObserver(this);
}
};
Regarding the error message you have - you don't have a method (at least in this question) with the signature that your code is apparently looking for. You have:
virtual void registerObserver(ISubscriber *observer)
{
subscribers.append(observer);
}
Your first file describes an ISubscriber but your second file inherits from an ISubsrciber (sic).
You have a typo in your file. Change to ISubscriber and you should have better luck!
here updateManager->registerObserver(this); you are sending it object of UpdateReceiver while it requires ISubscriber.
class
class UpdateReceiver: public ISubsrciber // wrong
class UpdateReceiver: public UpdateManager // right
should inherit UpdateManager not ISubsrciber?
Well I do see a few problems along your solution. Firstly you do have different forward declarations for the type ISubscriber as I stated in my earlier comment. Which results in your program not compiling.
These two wont match for sure.
virtual void registerObserver(ISubscriber *observer) {...}
class UpdateReceiver: public ISubsrciber {...}
^^^^
Secondly your notifyObserver implementation does need some rethinking as well. But since you kind of commented that code out, I'll leave this one up to you. Just remember that you're holding pointers to ISubscriber in your subscriber list when you're trying to iterate/loop over it.
Also the definition of unregisterObserver does not match your declaration.
virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void unregisterObserver(ISubscriber *observer) {...}
BUT
I would consider some major refactorings for your code. In my opinion you should not mix up the Interface of the Observerpattern with your application logic.
I think your solution should look similar to this. It's not complete and does not use your QT classes tho but you should get the idea. See the demo for a runnable solution.
class ISubscriber {
public:
virtual void update() = 0;
};
class Publisher {
std::vector<ISubscriber*> m_observerList;
public:
virtual void registerSubscriber(ISubscriber& observer);
virtual void unregisterSubscriber(ISubscriber& observer);
virtual void notifySubscribers();
};
class UpdateManager : public Publisher {
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
public:
virtual void setBaudRate(int newBaudRate);
virtual void setAspectRatio(int newAspectRatio);
virtual void setVolumeLevel(int newVolume);
int getBaudRate() const;
int getAspectRatio() const;
int getVolumeLevel() const;
};
class UpdateReceiver : public ISubscriber {
UpdateManager& m_manager;
public:
UpdateReceiver(UpdateManager& manager) : m_manager(manager) {
m_manager.registerSubscriber(*this);
}
virtual void update() {
// Process the new values
m_manager.getBaudRate();
m_manager.getAspectRatio();
m_manager.getVolumeLevel();
}
};
DEMO
I am experiencing a problem where a derived class does not have it's own version of a function called when it is called from a base class pointer. To better explain the classes are defined as below
Class Foo
{
public:
Foo();
virtual ~Foo();
virtual void Event();
}
//-----------------------
Class FooBar : public Foo
{
public:
FooBar();
virtual void Update() = 0;
virtual void Draw() = 0;
}
//-----------------------
Class FinalFoo : public FooBar
{
public:
FinalFoo();
void Update();
void Draw();
void Event();
}
There are other classes similar to FinalFoo. So I attempt to call Event on a pointer to a Foo object expecting that it would call the derived implementation. However, it would appear that it calls the base class version and that is all
FinalFoo* myThing = new FinalFoo();
Foo* baseThing = myThing;
baseThing->Event(); // I expected this to call FinalFoo::Event()
Assuming the above code is corrected, it actually does call FinalFoo::Event(). below is a complete and compilable example. Note, that it also adds the keyword override in strategic points: I'd bet that adding override in the original code, too (and compiling with a compiler aware of this keyword) would point out that your override isn't one.
#include <iostream>
class Foo
{
public:
virtual ~Foo() {}
virtual void Event() { std::cout << "Foo::Event()\n"; }
};
//-----------------------
class FooBar : public Foo
{
public:
virtual void Update() = 0;
};
//-----------------------
class FinalFoo : public FooBar
{
public:
FinalFoo() {}
void Update() override { std::cout << "FinalFoo::Update()\n"; }
void Event() override { std::cout << "FinalFoo::Event()\n"; }
};
int main()
{
FinalFoo myThing;
Foo* baseThing = &myThing;
baseThing->Event();
}
There is a nice state machine tutorial called UML Tutorial: Finite State Machines by Robert C. Martin. But I can't compile the sample code it provides. I got *FsmTest.cpp(46) : error C2664: 'SetState' : cannot convert parameter 1 from 'class UnlockedState *' to 'class TurnstileState '
Please, help. Thanks.
class Turnstile
{
public:
virtual void Lock();
virtual void Unlock();
virtual void Thankyou();
virtual void Alarm();
};
class TurnstileFSM;
class LockedState;
class UnlockedState;
class TurnstileState
{
public:
virtual void Coin(TurnstileFSM*) = 0;
virtual void Pass(TurnstileFSM*) = 0;
protected:
static LockedState lockedState;
static UnlockedState unlockedState;
};
class TurnstileFSM : public Turnstile
{
public:
void SetState(TurnstileState* s) {itsState = s;}
void Coin() {itsState->Coin(this);}
void Pass() {itsState->Pass(this);}
private:
TurnstileState *itsState;
};
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->SetState(&unlockedState);
t->Unlock();
}
virtual void Pass(TurnstileFSM* t)
{
t->Alarm();
}
};
class UnlockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->Thankyou();
}
virtual void Pass(TurnstileFSM* t)
{
t->SetState(&lockedState);
t->Lock();
}
};
LockedState TurnstileState::lockedState;
UnlockedState TurnstileState::unlockedState;
The problem is that when you try to call SetState() inside of LockedState::Coin(), the class UnlockedState is an incomplete type: it has been declared but not defined. In order to fix it, you'll need to move the definition of of Coin() to after that of UnlockedState:
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t);
...
};
class UnlockedState : public TurnstileState
{
...
};
void LockedState::Coin(TurnstileFSM* t)
{
...
}
Most likely this is because it does not know UnlockedState is a subclass of TurnstileState yet. Remove the function from inside the class to the end of the file:
class TurnstileFSM {
void SetState(TurnstileState* s);
};
void TurnstileFSM::SetState(TurnstileState* s) {itsState = s;}
In the example, the generated code should include the tscontext.h, and the TurnStyle class is derived from the context, which should be declared in *tscontext.h" as class TurnStyleContext.
In my case the generated code looks like this:
#include "tscontext.h" // the header file name for the context class"
// Forward Declarations
class TurnStyle;
//----------------------------------------------
// TurnStyleState: The base state class
//----------------------------------------------
class TurnStyleState
{
public:
virtual const char* StateName() const = 0;
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// State: Unlocked
//----------------------------------------------
class TurnStyleUnlockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Unlocked"; }
virtual void Pass( TurnStyle& );
virtual void Coin( TurnStyle& );
};
//----------------------------------------------
// State: Locked
//----------------------------------------------
class TurnStyleLockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Locked"; }
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// TurnStyle: The Finite State Machine class
//----------------------------------------------
class TurnStyle: public TurnStyleContext
{
public:
// Static State variables
static TurnStyleUnlockedState Unlocked;
static TurnStyleLockedState Locked;
TurnStyle(); // default Constructor
// Event functions
virtual void Coin() { itsState->Coin( *this ); }
virtual void Pass() { itsState->Pass( *this ); }
// State Accessor functions
void SetState( TurnStyleState& theState ) { itsState = &theState; }
TurnStyleState& GetState() const { return *itsState; }
const char* GetCurrentStateName() const { return itsState->StateName(); }
const char* GetVersion() const;
private:
TurnStyleState* itsState;
};
with the state machine defined this way:
Context TurnStyleContext // the name of the context class
FSMName TurnStyle // the name of the FSM to create
Initial Locked // the name of the initial state
// for C++ output
pragma Header tscontext.h" // the header file name for the context class, note the necessary "
{
Locked
{
Coin Unlocked Unlock
Pass Locked Alarm
}
Unlocked <BeforeUnlocked >AfterUnlocked
{
Coin Unlocked Thankyou
Pass Locked Lock
}
}
The context implements FSMError, Thankyou, Lock, Alarm, Unlock, BeforeUnlocked, AfterUnlocked