Here is the code I am currently troubleshooting:
void CTimer::notify()
{
std::vector<IObserver*>::iterator it;
for(it=observers.begin();it!=observers.end();++it)
{
ITimerNotification* notification = new CTimerNotification(now());
(*it)->readNotification(*notification);
}
}
class CTimerNotification : public ITimerNotification
{
public:
CTimerNotification(const timeval& t)
{
time = t;
}
protected:
timeval time;
private:
virtual ~CTimerNotification();
virtual void read(const IObserver& o) const
{
o.update(*this);
}
virtual const timeval& getTime() const
{
return time;
}
};
class IObserver
{
public:
virtual ~IObserver();
virtual void readNotification(const INotification&) const=0;
virtual void update(const INotification&) const=0;
};
class ITimerObserver : public IObserver
{
public:
virtual void update(const ITimerNotification&) const=0;
};
class TestObserver : public ITimerObserver
{
public:
virtual void readNotification(const INotification& n) const
{
n.read(*this);
}
virtual void update(const INotification& n) const
{
std::cout<<"???: TestObserver: update()!\n";
}
virtual void update(const ITimerNotification& n) const
{
std::cout<< n.getTime().tv_sec << "." << n.getTime().tv_usec <<": TestObserver: update()!\n";
}
};
So the code runs, CTimer::notify() gets called, which creates a TimerNotification and passes it to the observer via readNotification() which in turn calls the notification's read() method, which finally calls the observer's (hopefully) correct update() method.
The last step is what fails. It calls the update(INotification&) method instead of the desired update(ITimerNotification&) method.
What am I missing here for this attempted Double Dispatch pattern to work? It does not appear to be getting the correct type information to select the appropriate function call.
Thanks for any help!
CTimerNotification needs a read something like this
virtual void read(const IObserver& o) const {
ITimerObserver* to = dynamic_cast<ITimerObserver*>(&o);
if (to) {
to->update(*this);
} else {
o.update(*this);
}
}
and you need a using IObserver::update; in ITimerObserver.
Related
I've recently come across a couple of situations that I think could be cleaned up with a different design, but I don't know of any patterns that would fit.
In all of these situations, I have a few classes that partially share an API. For example, a logger class:
struct ILogger { virtual void log(string msg) = 0; };
struct StdOutLogger : public ILogger {
void log(string msg) override; // Log to stdout
};
struct FileLogger : public ILogger {
void log(string msg) override; // Log to file
};
struct GuiLogger : public ILogger {
void log(string msg) override; // Log to GUI
void draw();
void clear();
};
or perhaps:
struct Graphic {
virtual void draw();
virtual void setPosition();
// etc.
};
struct AnimatedGraphic : public Graphic {
void draw() override;
void start();
void stop();
void setLooping(bool loop);
};
Now, depending on who owns these objects, I might have a container of references/pointers to a common interface:
class LogManager {
std::vector<std::unique_ptr<ILogger>> _loggers;
// ...
};
Or I might keep the types separated and choose at runtime which one to use:
// This is already starting to get messy
class SomethingWithGraphic {
std::unique_ptr<Graphic> _graphic;
std::unique_ptr<AnimatedGraphic> _animatedGraphic;
// ...
};
The first solution is fine until I need to start using the functionality that is not part of the common interface. The second solution allows me to choose the one I need, but it is error prone and requires ugly branches everywhere.
I've come up with a couple of alternative solutions, but I haven't found one that really feels right.
Keep one owning container, and create additional containers that point to the owned objects, but through a different interface. (Requires that the containers be kept in sync)
Add all functions to interface, but leave implementations empty for objects that don't need the extra functions. (Those functions don't really belong as part of that interface)
Store variants of all potential types. (Feels like a hack, requires visitors everywhere)
Using the logger example:
//// 1 ////
struct IDrawable {
virtual void draw() = 0;
virtual void clear() = 0;
};
std::vector<std::unique_ptr<ILogger>> _loggers;
std::vector<IDrawable*> _drawableLoggers;
//// 2 ////
struct ILogger {
virtual void log(string msg) = 0;
virtual void draw() {};
virtual void clear() {};
};
struct StdOutLogger : public ILogger {
void log(string msg) override; // Log to stdout
};
struct FileLogger : public ILogger {
void log(string msg) override; // Log to file
};
struct GuiLogger : public ILogger {
void log(string msg) override; // Log to GUI
void draw() override;
void clear() override;
};
//// 3 ////
std::vector<std::variant<StdOutLogger, FileLogger, GuiLogger>> _loggers;
#1 seems the most correct I think, but still not the greatest.
Does anyone know of any patterns or structures that could clean this up?
A viable approach: you can use a vector of pointers or references to your interface and implement the visitor pattern for all those cases in which you want to get out of one instance its actual type and call a method that isn't part of the common interface.
Here is a minimal, working example:
#include<iostream>
#include<memory>
#include<vector>
struct Visitor;
struct Interface {
virtual void method() = 0;
virtual void accept(Visitor &) = 0;
};
struct A: Interface {
void method() override { std::cout << "A::method" << std::endl; }
void f() { std::cout << "A::f" << std::endl; }
void accept(Visitor &) override;
};
struct B: Interface {
void method() override { std::cout << "B::method" << std::endl; }
void g() { std::cout << "B::g" << std::endl; }
void accept(Visitor &) override;
};
struct Visitor {
void visit(A &a) { a.f(); }
void visit(B &b) { b.g(); }
};
void A::accept(Visitor &v) { v.visit(*this); }
void B::accept(Visitor &v) { v.visit(*this); }
int main() {
std::vector<std::unique_ptr<Interface>> vec;
vec.push_back(std::make_unique<A>());
vec.push_back(std::make_unique<B>());
Visitor visitor;
for(auto &&i: vec) {
i->method();
i->accept(visitor);
}
}
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 have a hirerchy of Message class and Processor class. Each processor can recieve one or more messages on the fly. As each message can have some differnt attributes, I've to downcast that message to the concrect message class, to actually process that.
As there are a no. of message classes and process classes, I don't want to use dynamic_cast.
I tried to use following code, but this is giving compile time error.
Also, I have the flexibility to attach a processor pointer with a message (if needed), but not the other way round.
class Message
{
public:
virtual const Message* const getMessage() const = 0;
};
class MA : public Message
{
public:
const MA* const getMessage() const {return this;}
void printMA() const{std::cout<<"I am MA"<<std::endl;}
};
class MB : public Message
{
public:
const MB* const getMessage() const {return this;}
void printMB() const{std::cout<<"I am MB"<<std::endl;}
};
class Processor
{
public:
virtual void process(const Message* m) = 0;
};
class PA : public Processor
{
public:
void process(const Message* m) {processM(m->getMessage());}
void processM(const MA* m) {m->printMA();}
void processM(const MB* m) {m->printMB();}
};
int main()
{
Message* m1 = new MA();
Message* m2 = new MB();
Processor* p1 = new PA();
p1->process(m1);
p1->process(m2);
return 0;
}
I used 'double dispatch' finally to get around this. Now, the only thing is that I need to add a function in MessageProcessor' class, whenever i add a new message type., but i think that is fine.
class MessageProcessor
{
public:
virtual void process(const MA*) const{std::cout<<"unhandled:MA"<<std::endl;}
virtual void process(const MB*) const{std::cout<<"unhandled:MB"<<std::endl;}
virtual void process(const MC*) const{std::cout<<"unhandled:MC"<<std::endl;}
};
class Message
{
public:
virtual void process(const MessageProcessor*) const = 0;
};
class MA : public Message
{
public:
void printMA() const{std::cout<<"I am MA"<<std::endl;}
virtual void process(const MessageProcessor* p) const {p->process(this);}
};
class MB : public Message
{
public:
void printMB() const{std::cout<<"I am MB"<<std::endl;}
virtual void process(const MessageProcessor* p) const {p->process(this);}
};
class MC : public Message
{
public:
void printMC() const{std::cout<<"I am MC"<<std::endl;}
virtual void process(const MessageProcessor* p) const {p->process(this);}
};
class Processor : public MessageProcessor
{
public:
void processM(const Message* m){m->process(this);}
};
class PA : public Processor
{
public:
void process(const MA* m) const {m->printMA();}
void process(const MB* m) const {m->printMB();}
};
class PB : public Processor
{
public:
void process(const MA* m) const {m->printMA();}
void process(const MC* m) const {m->printMC();}
};
int main()
{
const Message* m1 = new MA();
const Message* m2 = new MB();
const Message* m3 = new MC();
Processor* p1 = new PA();
p1->processM(m1);
p1->processM(m2);
p1->processM(m3);
Processor* p2 = new PB();
p2->processM(m1);
p2->processM(m2);
p2->processM(m3);
return 0;
}
The most general solution to your problem is probably the Visitor pattern.
The simplest thing to do is eliminate the getMessage() method, and make the print() pure virtual in Message and override this in MA and MB. Furthermore, you can make process() a pure virtual method in Process and override this in PA. See code below:
#include <iostream>
class Message
{
public:
const std::string _id;
Message(std::string id):_id(id) {}
virtual void print() const = 0;
virtual void other_fun() const = 0;
};
class MA : public Message
{
private: double d_;
public:
MA():Message("MA"), d_(0.0) {}
virtual void print() const
{
std::cout<<"I am MA"<<std::endl;
std::cout << "I also have a double" << std::endl;
}
virtual void other_fun() const { std::cout << "I am MA specific" << std::endl; }
void do_hoops () const { std::cout << "Hoop!"<<std::endl;}
};
class MB : public Message
{
private: int i_;
public:
MB():Message("MB"), i_(0) {}
virtual void print() const
{
std::cout<<"I am MB"<<std::endl;
std::cout << "I also have an int"<<std::endl;
}
virtual void other_fun() const { std::cout << "I am MB specific" << std::endl; }
void do_twist() const { std::cout << "Twist!"<<std::endl; }
};
class Processor
{
public:
const std::string _id;
Processor(std::string id) : _id(id){}
virtual void process(const Message* m) = 0;
};
class PA : public Processor
{
public:
PA():Processor("PA") {}
virtual void process(const Message* m)
{
m->print();
m->other_fun();
}
};
int main()
{
Message* m1 = new MA();
Message* m2 = new MB();
// generic handling of message
Processor* p1 = new PA();
p1->process(m1);
p1->process(m2);
// message specific stuff
dynamic_cast<MA*>(m1)->do_hoops();
dynamic_cast<MB*>(m2)->do_twist();
return 0;
}
Output on Ideone.
No casts are required, the virtual functions will be selected at runtime through dynamic dispatch (virtual table lookup etc.). Message and Process are abstract base classes ("interfaces") and MA, MB and PA are concrete classes implementing these interfaces. Ideally, you also would factor the std::string state out of the Message interface, but that's left as an exercise.
Casting would be required if you would call functions that are specific to a derived class, and if you know at runtime that you are in fact calling such a class. This is done through a dynamic_cast to the particular derived class your base class pointer is currently pointing to.
You have a design flaw. Signature of Processor::process suggests it takes a Message, then it should not break this promise by trying to access something that is not a public interface of Message.
You can make Process a template class (host) that inherits from user supplied policies. Policies here are the concrete Message classes. Something like this:
#include <iostream>
struct MA
{
void print ()
{
std::cout << "MA: I'm the interface" << std::endl;
}
void printMA ()
{
std::cout << "MA: I'm special" << std::endl;
}
};
struct MB
{
void print ()
{
std::cout << "MB: I'm the interface" << std::endl;
}
void printMB ()
{
std::cout << "MB: I'm special" << std::endl;
}
};
template <typename M>
struct Process :
public M
{
void process()
{
M::print();
}
};
int main ()
{
Process<MA> p1;
Process<MB> p2;
p1.print(); // MA: I'm the interface
p1.printMA(); // MA: I'm special
p2.print(); // MB: I'm the interface
p2.printMB(); // MB: I'm special
}
Policies have print method that defines its interface. They also have some special methods like printMA and printMB. Host class (here Process) acts as user's interface to the policies. It can use the interface methods from policy classes. Special policy methods can be invoked by the user through host class.
You've run into a limitation of C++. What you really want is for the polymorphism to work on the arguments to a method, not just the method that the arguments are called on. It's generally referred to as double dispatch. Unfortunately, while there are some kind-of work-arounds, I haven't seen any perfect ones. That Wikipedia article shows the generally accepted workaround (using the Visitor pattern).
I'm trying to use the visitor pattern to perform operations for the AST of my compiler but I can't seem to figure out an implementation that will work properly.
AST classes excerpt:
class AstNode
{
public:
AstNode() {}
};
class Program : public AstNode
{
public:
std::vector<std::shared_ptr<Class>> classes;
Program(const std::vector<std::shared_ptr<Class>>&);
void accept(AstNodeVisitor& visitor) const { visitor.visit(*this); }
};
class Expression : public AstNode
{
public:
Expression() {}
};
class Method : public Feature
{
public:
Symbol name;
Symbol return_type;
std::vector<std::shared_ptr<Formal>> params;
std::shared_ptr<Expression> body;
Method(const Symbol&, const Symbol&, const std::vector<std::shared_ptr<Formal>>&,
const std::shared_ptr<Expression>&);
feature_type get_type() const;
};
class Class : public AstNode
{
public:
Symbol name;
Symbol parent;
Symbol filename;
std::vector<std::shared_ptr<Feature>> features;
Class(const Symbol&, const Symbol&, const Symbol&,
const std::vector<std::shared_ptr<Feature>>&);
};
class Assign : public Expression
{
public:
Symbol name;
std::shared_ptr<Expression> rhs;
Assign(const Symbol&, const std::shared_ptr<Expression>&);
};
Visitor (partial implementation):
class AstNodeVisitor
{
public:
virtual void visit(const Program&) = 0;
virtual void visit(const Class&) = 0;
virtual void visit(const Attribute&) = 0;
virtual void visit(const Formal&) = 0;
virtual void visit(const Method&) = 0;
};
class AstNodePrintVisitor : public AstNodeVisitor
{
private:
size_t depth;
public:
void visit(const Program& node) {
for (auto cs : node.classes)
visit(*cs);
}
void visit(const Class&);
void visit(const Attribute&);
void visit(const Formal&);
void visit(const Method&);
};
How I'm using it:
AstNodePrintVisitor print;
ast_root->accept(print); // ast_root is a shared_ptr<Program>
The issue:
The Method Node contains a body member of type Expression - which is a base class. How will I visit it?
I thought maybe I could simply write an accept method for each AST node and do the traversal there instead. (ie. instead of calling visit() in the visitor, call accept() in the visitable then call visit(*this) so the calls will be polymorphic and the right visit() method of the visitor gets called.
However, if I do this, I will have no option for traversing top-down (operation then recurse) or bottom-up (recurse then operation) since I have to choose only one. By this I mean a PrintVisitor for example will need a top-down traversal of the AST but a TypeCheck will need a bottom-up approach.
Is there a way around this? Or am I over-engineering things? Right now I think the fastest way is to just implement the methods in the nodes themselves.
Let's begin with a minor correction to the craft of a Visitor:
void visit(const Program& node) {
for (auto cs : node.classes)
visit(*cs);
}
the call visit(*cs) should be cs->accept(*this) to allow for virtual dispatch, in the generic case.
And now to the main question: the control of traversal order.
A visitor can only really visit a tree in a depth first way, breadth first may be implemented but is quirky in a single visit method (you basically need to separate visitation from iterations on children).
On the other hand, even in a depth first traversal, you may chose whether to act on the parent either before or after having visited the children.
The typical way to do so would be to provide an intermediate layer between the pure base class and the real actor, for example:
class RecursiveAstNodeVisitor: public AstNodeVisitor
{
public:
// returns whether or not to stop recursion
virtual bool actBefore(Program const&) { return false; }
virtual void actAfter(Program const&) {}
virtual bool actBefore(Class const&) { return false; }
virtual void actAfter(Class const&) {}
// ... You get the idea
virtual void visit(Program const& p) {
if (actBefore(p)) { return; }
for (auto c: p.classes) {
c->accept(*this);
}
actAfter(p);
}
// ... You get the idea
};
The overrider is free to act either before or after the recursion occurs... and of course may act on both!
class PrintAstNodeVisitor: public RecursiveAstNodeVisitor {
public:
PrintAstNodeVisitor(std::ostream& out): _out(out), _prefix() {}
virtual bool actBefore(Program const& p) {
_out << "{\n";
_out << " \"type\": \"Program\",\n";
_out << " \"name\": \" << p.name << "\",\n";
_out << " \"classes\": [\n";
_prefix = " ";
return false;
}
virtual void actAfter(Program const& p) {
_out << " ]\n";
_out << "}\n";
}
virtual bool actBefore(Class const& c) {
_out << _prefix << "{\n";
_out << _prefix << " \"type\": \"Class\",\n";
// ...
}
private:
std::ostream& _out;
std::string _prefix;
};
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