>
> If I wanted to declare a pointer to this function:
>
> int foo(int bar);
>
> What would be the syntax for the declaration?
>
> The best I came up with was this:
>
> (int)(*)(int) pfoo = &foo;
>
Try:
int (*pfoo)(int bar)=foo;
You don't need to do &foo.
If you want to declare an array of function pointers you have to do it like this:
int (*pfunarray[])(int bar)={
one_fun,
another_fun,
andsoon_fun,
NULL
};
The NULL is only needed if you dynamically want to scan the array and like to know where it ends.
Note that int C++ you can only get a pointer to a class member function if it is declared as static (because of the this pointer that otherwise also would be needed).
Regards / Ruben
==============================
Ruben Jönsson
AB Liros Electronic
Box 9124, 200 39 Malmö, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 spam_OUTrubenTakeThisOuTpp.sbbs.se
==============================
Isn't it much more readable to do it with typedefs?
// Define a function pointer type
typedef int (*FooFuncPtr)(int bar);
FooFuncPtr pfoo = &bar; // or without the "&"
FooFuncPtr pfunarry[] = {
// etc..
};
Believe me, the next person to maintain your code will thank you! And so
will you when you come back to it in 6 months.. Using good type and variable
names is also important. So are comments, but that's another story..
</CODE STYLE POLICE MODE>
Sorry, my software engineering background is showing.. :)
> int (*pfoo)(int bar)=foo;
>
> If you want to declare an array of function pointers you have
> to do it like this:
>
> int (*pfunarray[])(int bar)={
> one_fun,
> another_fun,
> andsoon_fun,
> NULL
> };
> Note that int C++ you can only get a pointer to a class member
> function if it is declared as static (because of the this
> pointer that otherwise also would be needed).
Nope...
pointers to non-static member functions are also supported (unless you use
an old version of the M$ C++ compiler)
> <snip>
>
> > Note that int C++ you can only get a pointer to a class member
> > function if it is declared as static (because of the this
> > pointer that otherwise also would be needed).
>
> Nope...
>
> pointers to non-static member functions are also supported (unless you
> use an old version of the M$ C++ compiler)
>
> e.g.
>
> class FOO
> {
> public:
> int xfunc(int, int);
> };
>
> int (FOO::*func)(int, int);
>
> func = &FOO::xfunc;
>
> FOO some_foo,
> *foo_ptr;
>
> (some_foo.*xfunc)(1, 2);
>
> (foo_ptr->*xfunc)(1, 2);
>
> Regards
> Sergio Masci
Yes, but this would (as You show) require both a pointer to an object (or an instance of one) and a pointer to the function.
Have You ever used pointers to nonstatic member functions? If so, what was the purpose? I can't see any good reason to use them, but I am always willing to learn (and I am by no means a C++ expert:) ).
Regards / Ruben
==============================
Ruben Jönsson
AB Liros Electronic
Box 9124, 200 39 Malmö, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 @spam@rubenKILLspampp.sbbs.se
==============================
>Have You ever used pointers to nonstatic member functions? If
>so, what was the purpose? I can't see any good reason to use
>them, but I am always willing to learn (and I am by no means a
>C++ expert:) ).
>Regards / Ruben
Indeed, and often. I use them for many of the same reasons that I use
ordinary function pointers. A simple example would be a class that
implemented a state machine where each state was handled by a different
member function. You would then use a member function pointer to keep track
of the current state.
> >Have You ever used pointers to nonstatic member functions? If
> >so, what was the purpose? I can't see any good reason to use
> >them, but I am always willing to learn (and I am by no means a
> >C++ expert:) ).
>
> >Regards / Ruben
>
>
> Indeed, and often. I use them for many of the same reasons that I use
> ordinary function pointers. A simple example would be a class that
> implemented a state machine where each state was handled by a
> different member function. You would then use a member function
> pointer to keep track of the current state.
>
> Bob Ammerman
> RAm Systems
>
What would be the benefit of this compared to just a simple switch/case?
CSomeClass::HandleState()
{
switch (m_iState){
case (STATE_IDLE): StateIdle(); break;
case (STATE_SORT): StateSort(); break;
case (STATE_SORTDONE): StateSortDone(); break;
default:
// handle exception (which function pointers wont)
}
}
Ruben
==============================
Ruben Jönsson
AB Liros Electronic
Box 9124, 200 39 Malmö, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 spamBeGonerubenspamBeGonepp.sbbs.se
==============================
> >Have You ever used pointers to nonstatic member functions? If
> >so, what was the purpose? I can't see any good reason to use
> >them, but I am always willing to learn (and I am by no means a
> >C++ expert:) ).
>
> >Regards / Ruben
>
>
> Indeed, and often. I use them for many of the same reasons that I use
> ordinary function pointers. A simple example would be a class that
> implemented a state machine where each state was handled by a
> differentmember function. You would then use a member function
> pointer to keep track
> of the current state.
The original reason for asking this question was to implement a system where a flag variable would be used to index an array of pointers to functions. Alas, as I was wanting to implement this in CCS, it was not to be. I will have to use the dreaded switch() containing function calls instead.
> >Have You ever used pointers to nonstatic member functions? If
> >so, what was the purpose? I can't see any good reason to use
> >them, but I am always willing to learn (and I am by no means a
> >C++ expert:) ).
>
> >Regards / Ruben
>
>
> Indeed, and often. I use them for many of the same reasons that I use
> ordinary function pointers. A simple example would be a class that
> implemented a state machine where each state was handled by a
> different member function. You would then use a member function
> pointer to keep track of the current state.
>
> Bob Ammerman
> RAm Systems
>
- What would be the benefit of this compared to just a simple
- switch/case?
- CSomeClass::HandleState()
- {
- switch (m_iState){
- case (STATE_IDLE): StateIdle(); break;
- case (STATE_SORT): StateSort(); break;
- case (STATE_SORTDONE): StateSortDone(); break;
- default:
- // handle exception (which function pointers wont)
- }
-}
-Ruben
Exactly the same as the advantages to using function pointers in the
non-class, non-member function way for state machines. You don't have that
ugly switch statement that has to be maintained everytime you add a new
state. You also don't have to create a separate enumeration type for the
states. The names of the functions themselves serve that purpose.
Oh, and by the way, there is nothing wrong with having a null in a member
function pointer, so you can say:
if (mfp)
-- call the function
else
-- handle exceptional (or default) case
> - What would be the benefit of this compared to just a simple
> - switch/case?
>
> - CSomeClass::HandleState()
> - {
> - switch (m_iState){
> - case (STATE_IDLE): StateIdle(); break;
> - case (STATE_SORT): StateSort(); break;
> - case (STATE_SORTDONE): StateSortDone(); break;
> - default:
> - // handle exception (which function pointers wont) -
> } -}
>
> -Ruben
>
> Exactly the same as the advantages to using function pointers in the
> non-class, non-member function way for state machines. You don't have
> that ugly switch statement that has to be maintained everytime you add
> a new state. You also don't have to create a separate enumeration type
> for the states. The names of the functions themselves serve that
> purpose.
Well, I guess it is a matter of taste. I think of the switch/case as a lookup table (with only calls to the actual state functions in it), quite easy to maintain. The enumerated type also gives me a way to group states in ranges that can be easily tested (if (m_iState>=STATE_MENU_FIRST || m_iState<=STATE_MENU_LAST)). It also serves as an offset for other tables than the state functions, tables of strings with explaining text, or parameter values for example.
I can also directly check the state variable in a debugger to see what state the machine is in. Or perhaps the debugger can resolve pointers to functions to their actual function names?
So I think I will stick to the switch statement with an enumerated type for the states. I could consider an array with pointers to the state functions but the enumerated type definitely stays :-)
>
> Oh, and by the way, there is nothing wrong with having a null in a
> member function pointer, so you can say:
>
> if (mfp)
> -- call the function
> else
> -- handle exceptional (or default) case
That would be okay for null but not for any random value, not pointing to any function. An uninitialized or overwritten function pointer, for example. This would also be catched by the default case within a switch statement.
>
> Bob Ammerman
> RAm Systems
When I first said that you can't have pointers to non static member functions in C++, I was thinking about that a function pointer can't point to both the object (the this pointer) and the function within it (it can't be used as a callback, for example). However, I wasn't aware of the fact that you actually can have pointers to nonstatic member functions, if you have a way to supply the object for it (for example within the object itself). So I have learned something new today also :-)
Ruben
==============================
Ruben Jönsson
AB Liros Elektronik
Box 9124, 200 39 Malmö, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 EraseMErubenpp.sbbs.se
==============================
> >Have You ever used pointers to nonstatic member functions? If
> >so, what was the purpose? I can't see any good reason to use
> >them, but I am always willing to learn (and I am by no means a
> >C++ expert:) ).
>
> >Regards / Ruben
>
>
> Indeed, and often. I use them for many of the same reasons that I use
> ordinary function pointers. A simple example would be a class that
> implemented a state machine where each state was handled by a different
> member function. You would then use a member function pointer to keep track
> of the current state.
Bob,
I missed some of the posts on this thread so maybe I missed something
here -- Why would you use pointers to nonstatic member functions? Wouldn't
it be easier to use pointers to classes that contain virtual functions?
Or for State Machines, wouldn't it be easier to create a State Machine
class?
Scott
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
> On Thu, 12 Dec 2002, Bob Ammerman wrote:
>
> > >Have You ever used pointers to nonstatic member functions? If
> > >so, what was the purpose? I can't see any good reason to use
> > >them, but I am always willing to learn (and I am by no means a
> > >C++ expert:) ).
> >
> > >Regards / Ruben
> >
> >
> > Indeed, and often. I use them for many of the same reasons that I use
> > ordinary function pointers. A simple example would be a class that
> > implemented a state machine where each state was handled by a different
> > member function. You would then use a member function pointer to keep
track
> > of the current state.
>
> Bob,
>
> I missed some of the posts on this thread so maybe I missed something
> here -- Why would you use pointers to nonstatic member functions? Wouldn't
> it be easier to use pointers to classes that contain virtual functions?
This can work quite well. I am assuming you mean that each state is a
subclass of a generate State class and has a virtual 'Execute' method. There
are however two significant problems with this technique:
1: Where do you put data needed by the state machine as a whole?
2: When do you 'new' up a state and 'delete' and old one?
> Or for State Machines, wouldn't it be easier to create a State Machine
> class?
I'm not sure what you mean by this.
> Scott
>
Bob Ammerman
RAm Systems
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
> > <snip>
> >
> > > Note that int C++ you can only get a pointer to a class member
> > > function if it is declared as static (because of the this
> > > pointer that otherwise also would be needed).
> >
> > Nope...
> >
> > pointers to non-static member functions are also supported (unless you
> > use an old version of the M$ C++ compiler)
> >
> > e.g.
> >
> > class FOO
> > {
> > public:
> > int xfunc(int, int);
> > };
> >
> > int (FOO::*func)(int, int);
> >
> > func = &FOO::xfunc;
> > FOO some_foo,
> > *foo_ptr;
> >
> > (some_foo.*xfunc)(1, 2);
> >
> > (foo_ptr->*xfunc)(1, 2);
> >
> > Regards
> > Sergio Masci
>
> Yes, but this would (as You show) require both a pointer to an
> object (or an instance of one) and a pointer to the function.
>
> Have You ever used pointers to nonstatic member functions? If
> so, what was the purpose? I can't see any good reason to use
> them, but I am always willing to learn (and I am by no means a
> C++ expert:) ).
>
> Regards / Ruben
Yes I've used and continue to use pointers to member functions quite a lot.
I use them particularly when I have some kind of manager object that does
not know about the object it is managing. You would create the manager with
the object to be managed together with one or more pointers to methods that
should be applied depending on some condition. While the program is running
you might change the method to be applied to the managed object. You might
do this many times.
Consider a SWITCH object that needs to signal another object when a given
switch is opened or closed. You could derive a LAMP object from an EVENT
object that knows about switch_on and switch_off events. Then when the
SWITCH object needs to signal the LAMP it can do so via the correct EVENT
method. You would then extend the EVENT class to encompass all sorts of
events because you have many components in your system. The problem now is
that your EVENT class must know about all the possible types of events that
can occur AND your event generating objects and your event processing
objects must agree on the signalling method. This can get very messy very
quickly especially if you want to connect an event generator to an
incompatible event processor. Say you have a LAMP object that has two
switches attached one for on/off and the other for full brightness / dim.
By using pointers to member functions you can obviate the need for a special
EVENT class, you can get rid of the messy mapping mechanism, you end up with
a succinct solution.
In essence you keep knowledge of the workings of the objects better hidden
from each other, you don't smear the logic halfway across your source.
In fact the whole GUI and derived applications work this way. There is no
windows type event loop. There is very little that sits between a mouse
event and a method processing the event (certainly no delay loop)
Something which may have escaped your immediate notice is that you can also
do
When ever I need to represent some abstract notion that is not as simple as
it first appears, I reach for my copy of "Design Patterns" (Gamma et al).
ISBN: 0-201-63361-2. I can't recommend this book enough - it is really
useful when writing OO software. It focuses on C++, but the patterns apply
to any OO language.
The particular pattern of interest is called "State". Basically, you allow
an object to "apparently change its class" based on internal state changes..
Essentially, the engine maintains a pointer to the current state. It then
delegates all processing to that state. The states them selves are based on
a single base class which is granted friendship to allow it to set new
states. It can also be setup to access member data from the engine to decide
what to do.
Each state is then derived from the State base class. And implemented as a
Singleton (a class of which only one instance is ever created). When a new
state is required, it is accessed by using the Instance() method which is
the only way to create one because the constructor is made private. The
first time a singleton is created it "new"s itself and keeps a copy of the
pointer. then returns that same pointer for each call to Instance().
Because it is a singleton, it must not maintain any instance data. Therefore
all data is put into the Engine which is passed into all processing calls.
Lets see:
*** NOT TESTED OR COMPLETE CODE, but should give you the idea. ***
// Main state engine. This is the public interface to the
// state engine
class TheStateEngine
{
public:
// Processing
void Process() { m_pState->Process(this) }; // should NULL Check
private:
// allow the base class for all the states to
// set new states.
friend class State;
void ChangeState( State *pNewState );
// The current State
State *m_pState;
}
// Base class for all the different states
class State
{
public:
// Processing - default implementation is do nothing
virtual void Process( TheStateEngine *pEngine ) {};
protected:
// Change state
void ChangeState( TheStateEngine *pEngine, State *pNewState )
{
pEngine->ChangeState( pNewState ); // should null check
};
}
// Example state
class FirstState : public State
{
public:
// Singleton instance (returning base class intentional)
static State* Instance();
// Singleton stuff
static FirstState::m_pInstance = NULL;
State* FirstState::Instance()
{
// create new instance on first call
if( NULL == m_pInstance )
m_pInstance = new FirstState();
return m_pInstance;
}
void FirstState::Process( TheStateEngine *pEngine )
{
// processing here
// Change state (AnotherState is similar for FirstState)
ChangeState( pEngine, AnotherState::Instance() );
}
Clear as mud? :P
Not that useful for simple state engines, but if there is significant
processing that is state dependant, it makes organising it all much easier.
Also note the all the State derived classes are never seen outside the
TheStateEngine and so can change without affecting ANY code that calls it.
There is also nothing to stop you defining a series of different "process"
functions. For example you could assign a function to each button on your
interface etc.. Then in a menuing state engine, each button will do
different things based on the currently set state class.
You don't need to use singletons for the state classes, but it gets rid of
the new/delete overhead. As long as you are careful about maintaining
instance data in the correct place so that if you have two instances of
state engines using the same state classes the data doesn't get clobbered.
(store it in the Engine if possible).
> > I missed some of the posts on this thread so maybe I missed
> something
> > here -- Why would you use pointers to nonstatic member
> functions? Wouldn't
> > it be easier to use pointers to classes that contain
> virtual functions?
>
> This can work quite well. I am assuming you mean that each state is a
> subclass of a generate State class and has a virtual
> 'Execute' method. There
> are however two significant problems with this technique:
>
> 1: Where do you put data needed by the state machine as a whole?
>
> 2: When do you 'new' up a state and 'delete' and old one?
>
> > Or for State Machines, wouldn't it be easier to create a
> State Machine
> > class?
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
I think I see what you are trying to achieve. A useful pattern (see my
previous post) would be the "Command" pattern.
It nicely handles separating an invoker (Menu, gui, Switch etc) from an
target (Light). It does this be creating a common "Command" base class from
which concrete commands are derived.
From you explanation below, you derived the Light from the Event (command)
but this could be quite cumbersome if you needed many different commands
with different actions. Better to give a concrete implementation command
knowledge of how to invoke a command on the target.
As an added benefit, one you start using commands, you can reasonable easily
implement Macros (a command that maintains a list of other commands to
execute when called) and undo/redo.
So for you example something like:
*** NOT TESTED OR COMPLETE CODE ***
// Abstract Base Class: Command
class Command
{
public:
virtual ~Command();
class Switch
{
void AttachCommand( Command *pCmd );
// Call when switch even happens
void Invoke() { m_pCmd->Execute(); };
private:
Command *m_pCmd; // Or this could be a list etc..
}
// A Command to turn on a light
class LightOnCommand : public Command
{
public:
// when constructed, we will need a target
LightOnCommand( Light *pTargetLight );
You could also implement a LighOffCommand or a LighToggleCommand
To use (in your manager that sets it all up)
Light ALight;
Switch ASwitch;
Command *pCmd;
pCmd = new LighOnCommand( &ALight );
ASwitch.AttachCommand( pCmd );
ASwitch.Invoke();
This may look like a lot of work, but simple commands that don't need any
arguments to their targets can be implemented with templates.
The main benefit is that you can easily extend the commands, by adding new
ones at any time. The Invoker (Switch) doesn't care what they do it knows
only one interface (Command). The concrete commands (LightOnCommand) can be
tightly coupled to their targets if you really need to (you can have then
created solely by the target class if you need and so completely hide them
from the rest of the application).
You can also easily add things like macros and undo/redo.
> Consider a SWITCH object that needs to signal another object
> when a given
> switch is opened or closed. You could derive a LAMP object
> from an EVENT
> object that knows about switch_on and switch_off events. Then when the
> SWITCH object needs to signal the LAMP it can do so via the
> correct EVENT
> method. You would then extend the EVENT class to encompass
> all sorts of
> events because you have many components in your system. The
> problem now is
> that your EVENT class must know about all the possible types
> of events that
> can occur AND your event generating objects and your event processing
> objects must agree on the signalling method. This can get
> very messy very
> quickly especially if you want to connect an event generator to an
> incompatible event processor. Say you have a LAMP object that has two
> switches attached one for on/off and the other for full
> brightness / dim.
>
> By using pointers to member functions you can obviate the
> need for a special
> EVENT class, you can get rid of the messy mapping mechanism,
> you end up with
> a succinct solution.
>
> In essence you keep knowledge of the workings of the objects
> better hidden
> from each other, you don't smear the logic halfway across your source.
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
> Yes I've used and continue to use pointers to member functions quite a
> lot.
>
> I use them particularly when I have some kind of manager object that
> does not know about the object it is managing. You would create the
> manager with the object to be managed together with one or more
> pointers to methods that should be applied depending on some
> condition. While the program is running you might change the method to
> be applied to the managed object. You might do this many times.
>
> Consider a SWITCH object that needs to signal another object when a
> given switch is opened or closed. You could derive a LAMP object from
> an EVENT object that knows about switch_on and switch_off events. Then
> when the SWITCH object needs to signal the LAMP it can do so via the
> correct EVENT method. You would then extend the EVENT class to
> encompass all sorts of events because you have many components in your
> system. The problem now is that your EVENT class must know about all
> the possible types of events that can occur AND your event generating
> objects and your event processing objects must agree on the signalling
> method. This can get very messy very quickly especially if you want to
> connect an event generator to an incompatible event processor. Say you
> have a LAMP object that has two switches attached one for on/off and
> the other for full brightness / dim.
>
> By using pointers to member functions you can obviate the need for a
> special EVENT class, you can get rid of the messy mapping mechanism,
> you end up with a succinct solution.
Would this be the same type of mechanism that is used by message maps in windows MFC programming?
Ruben
==============================
Ruben Jönsson
AB Liros Elektronik
Box 9124, 200 39 Malmö, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 rubenSTOPspamspam_OUTpp.sbbs.se
==============================
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
> Hi,
>
> I think I see what you are trying to achieve. A useful pattern (see my
> previous post) would be the "Command" pattern.
>
> It nicely handles separating an invoker (Menu, gui, Switch etc) from an
> target (Light). It does this be creating a common "Command" base class
from
> which concrete commands are derived.
>
> From you explanation below, you derived the Light from the Event (command)
> but this could be quite cumbersome if you needed many different commands
> with different actions. Better to give a concrete implementation command
> knowledge of how to invoke a command on the target.
>
> As an added benefit, one you start using commands, you can reasonable
easily {Quote hidden}
> implement Macros (a command that maintains a list of other commands to
> execute when called) and undo/redo.
>
> So for you example something like:
>
> *** NOT TESTED OR COMPLETE CODE ***
>
> // Abstract Base Class: Command
> class Command
> {
> public:
> virtual ~Command();
>
> virtual void Execute() = 0;
> private:
> Command(); // Private Constructor
> };
>
> class Light
> {
> void TurnOn();
> void TurnOff();
> bool IsOn();
> // etc...
> };
>
> class Switch
> {
> void AttachCommand( Command *pCmd );
>
> // Call when switch even happens
> void Invoke() { m_pCmd->Execute(); };
>
> private:
> Command *m_pCmd; // Or this could be a list etc..
> }
>
>
> // A Command to turn on a light
> class LightOnCommand : public Command
> {
> public:
> // when constructed, we will need a target
> LightOnCommand( Light *pTargetLight );
>
> virtual void Execute();
> private:
> Light *m_pTargetLight;
> };
>
> // Implementation of LightOnCommand
> LightOnCommand::LightOnCommand( Light *pTargetLight )
> {
> m_pTargetLight = pTargetLight;
> }
>
> void LightOnCommand::Execute()
> {
> m_pTargetLight->TurnOn();
> }
>
> You could also implement a LighOffCommand or a LighToggleCommand
>
> To use (in your manager that sets it all up)
>
> Light ALight;
> Switch ASwitch;
> Command *pCmd;
>
> pCmd = new LighOnCommand( &ALight );
> ASwitch.AttachCommand( pCmd );
>
> ASwitch.Invoke();
>
> This may look like a lot of work, but simple commands that don't need any
> arguments to their targets can be implemented with templates.
>
> The main benefit is that you can easily extend the commands, by adding new
> ones at any time. The Invoker (Switch) doesn't care what they do it knows
> only one interface (Command). The concrete commands (LightOnCommand) can
> tightly coupled to their targets if you really need to (you can have then
> created solely by the target class if you need and so completely hide them
> from the rest of the application).
>
> You can also easily add things like macros and undo/redo.
>
> Cheers,
> Ash.
>
> ---
> Ashley Roll
> Digital Nemesis Pty Ltd
> http://www.digitalnemesis.com
> Mobile: +61 (0)417 705 718
>
Sorry Ash, too convoluted for my liking. I prefer to use something like
this:
I think I understand why you think it is too convoluted.. It does look like
it, but bear with me.. :)
In the end there is a trade off between complexity and flexibility. In your
case you chose one way. I would have chosen a different. It really depends
on the amount of flexibility needed later (and sometimes this is not easy to
determine when you are writing the code).
Please Note, I don't think you are wrong in using pointers like this. I'm
just trying to demonstrate an alternative that may be useful in another
project or just as a mental exercise ;)
I would agree for the simple Light/Switch case that the pointer solution you
use is simpler. However, lets extend the example to handle an apparently
simple extra requirement:
Staying with your electrical analogue, Lets say that we now have a motor
that moves something. It has a "position" that can be set.
Now say we want to have 3 switches, "left", "mid", and "right".
With the pointer method, we would need to implement one of two things:
1. Add functions to the motor class for "left" "mid" and "right".
2. Allow the Switch to store a parameter to pass to a general "move"
function.
Option 1 is doable, but really is adding extraneous stuff to the motor
class, do you keep extending this interface each time a new position is
needed. This is not very elegant, and arguably will cause a maintenance
nightmare in the future.
Option 2 means that a special version of a switch is needed just for motors.
Alternatively switches could be extended to take an argument and return it
when invoking the function pointers. However then all the code needs to be
changes on all the object currently using the switch mechanism. Also this
would probable need to be handled as a void* so arbitrary data can be
passed. Now the issue is you have designed out type safety in your target
class interfaces, not a beneficial thing. There are also going to be issues
with memory ownership and freeing.
With the command pattern, to implement this new functionality is simple.
There are no changes to the Switch class..
class Motor
{
void Move(int position);
// etc.
};
class MoveMotorCommand : public Command
{
public:
// when constructed, we will need a target
MoveMotorCommand ( Motor *pTarget, int NewPosition );
virtual void Execute();
private:
Motor *m_pTarget;
int m_NewPosition;
};
MoveMotorCommand::MoveMotorCommand( Motor *pTarget, int NewPosition )
{
m_pTarget = pTarget;
m_NewPosition = NewPosition;
}
Then you can construct as many different switches with different motor
positions as you like:
Motor TheMotor;
Switch MoveLeftSwitch;
Switch MoveRightSwitch;
Switch MoveMidSwitch;
Command *pCmd;
pCmd = new MoveMotorCommand( &TheMotor, 0 );
MoveLeftSwitch.AttachCommand( pCmd );
pCmd = new MoveMotorCommand( &TheMotor, 128 );
MoveRightSwitch.AttachCommand( pCmd );
pCmd = new MoveMotorCommand( &TheMotor, 256 );
MoveMidSwitch.AttachCommand( pCmd );
MoveMidSwitch.Invoke(); // when pressed
Or perhaps you want to implement a switch that turns on a number of lights..
or turns on a light and moves a motor.. You could implement a "macro"
command. You would attach arbitrary other commands to this macro command. It
would add them to an ordered list then when executed, it would execute each
one in turn.
It really does depend on your needs. A GUI is a prime example of where this
can really be helpful. The same mechanism can be used for menus, tool
buttons, and a command parser. As an added benefit, it is possible to
implement special commands that don't really have a "target" object but
alter global state or create a new window or document etc.. All with the
same Command infrastructure.
Basically, it only looks convoluted until you need to implement some extra
functionality, then it makes it really easy and neat.
> Hi Sergio,
>
> I think I understand why you think it is too convoluted.. It does look
like
> it, but bear with me.. :)
>
> In the end there is a trade off between complexity and flexibility. In
your
> case you chose one way. I would have chosen a different. It really depends
> on the amount of flexibility needed later (and sometimes this is not easy
to
> determine when you are writing the code).
>
> Please Note, I don't think you are wrong in using pointers like this. I'm
> just trying to demonstrate an alternative that may be useful in another
> project or just as a mental exercise ;)
>
> I would agree for the simple Light/Switch case that the pointer solution
you
> use is simpler. However, lets extend the example to handle an apparently
> simple extra requirement:
Hi Ash,
Ok keeping this friendly and just to throw a little more light on pointers
to methods.
We should firstly show the onlooker one of the aspects that was bothering me
when I said I thought it was too convoluted. That is, your switch can handle
either an ON condition or an OFF condition. It cannot handle both. To do so
you would need to add another intermediate messaging class LightOffCommand
(if we follow your previous naming convention). Your lamp would need to know
whether it is currently on and ignore requests to turn on or whether it is
currently off and ignore requests to turn off. A real switch cannot be
turned on if it is already on, or off if it is already off. So to model
the switch accurately you would have to build the logic into the switch not
the lamp (as I have in fact done).
>
> Staying with your electrical analogue, Lets say that we now have a motor
> that moves something. It has a "position" that can be set.
>
> Now say we want to have 3 switches, "left", "mid", and "right".
>
> With the pointer method, we would need to implement one of two things:
>
> 1. Add functions to the motor class for "left" "mid" and "right".
> 2. Allow the Switch to store a parameter to pass to a general "move"
> function.
>
> Option 1 is doable, but really is adding extraneous stuff to the motor
> class, do you keep extending this interface each time a new position is
> needed. This is not very elegant, and arguably will cause a maintenance
> nightmare in the future.
If we have a motor with three input levels on it I would want it to be a
different motor to one that only has an off/on input. I would only have a
problem with the motor class if I tried to keep all my options open by
adding on, off, left, mid, right, up, down, sideways, insideout blah blah
blah to a motor base class. By using pointers to methods you can point to a
method in one class that does not exist in another class and visa versa.
Provided you apply the method to the right type of object there is no
conflict, and you certainly don't have to worry about propagating virtual
methods all over the place.
e.g.
class MOTOR : public MTASK
{
// NOTE the absense of ON OFF or HIGH methods
}
class MOTOR_ONE_SPEED : public MOTOR
{
void on(void);
void off(void);
}
class MOTOR_TWO_SPEED : public MOTOR
{
void high(void);
void on(void);
void off(void);
}
Then if we continue with the simple switch which you first introduced
class SWITCH
{
MTASK *obj;
void (MTASK::*event_func)(void));
>
> Option 2 means that a special version of a switch is needed just for
motors.
> Alternatively switches could be extended to take an argument and return it
> when invoking the function pointers. However then all the code needs to be
> changes on all the object currently using the switch mechanism. Also this
> would probable need to be handled as a void* so arbitrary data can be
> passed. Now the issue is you have designed out type safety in your target
> class interfaces, not a beneficial thing. There are also going to be
issues
> with memory ownership and freeing.
No this is not the case. Yes I could easily have multiple types of switches
with the pointer to method stuff and I would not need to use void * as an
arbitrary data passing mechanism.
I think the problem here is that you are locked into the virtual method mode
of thinking. In which you have a pointer to a base class and you want to
apply a method to an object of a derived class. You see the only way to
access the method is by having a virtual instance in the base. Naturally all
overloaded methods must take the same parameters. BUT if you scrub the
virtual method and point directly to the real method, then the name becomes
just a label AND two methods with the same name in two different classes CAN
have different parameters and be accessed via a pointer to method without
conflict.
>
> With the command pattern, to implement this new functionality is simple.
> There are no changes to the Switch class..
>
> class Motor
> {
> void Move(int position);
> // etc.
> };
>
> class MoveMotorCommand : public Command
> {
> public:
> // when constructed, we will need a target
> MoveMotorCommand ( Motor *pTarget, int NewPosition );
>
> virtual void Execute();
> private:
> Motor *m_pTarget;
> int m_NewPosition;
>
> };
>
> MoveMotorCommand::MoveMotorCommand( Motor *pTarget, int NewPosition )
> {
> m_pTarget = pTarget;
> m_NewPosition = NewPosition;
> }
>
> MoveMotorCommand::Execute()
> {
> pTarget->Move( m_NewPosition );
> }
>
> Then you can construct as many different switches with different motor
> positions as you like:
>
> Motor TheMotor;
> Switch MoveLeftSwitch;
> Switch MoveRightSwitch;
> Switch MoveMidSwitch;
> Command *pCmd;
>
> pCmd = new MoveMotorCommand( &TheMotor, 0 );
> MoveLeftSwitch.AttachCommand( pCmd );
>
> pCmd = new MoveMotorCommand( &TheMotor, 128 );
> MoveRightSwitch.AttachCommand( pCmd );
>
> pCmd = new MoveMotorCommand( &TheMotor, 256 );
> MoveMidSwitch.AttachCommand( pCmd );
>
> MoveMidSwitch.Invoke(); // when pressed
>
> Or perhaps you want to implement a switch that turns on a number of
lights..
> or turns on a light and moves a motor.. You could implement a "macro"
> command. You would attach arbitrary other commands to this macro command.
It
> would add them to an ordered list then when executed, it would execute
each
> one in turn.
>
> It really does depend on your needs. A GUI is a prime example of where
this
> can really be helpful. The same mechanism can be used for menus, tool
> buttons, and a command parser. As an added benefit, it is possible to
> implement special commands that don't really have a "target" object but
> alter global state or create a new window or document etc.. All with the
> same Command infrastructure.
Ok, if we're going to talk about GUIs have a look at the XC GUI which forms
the heart of the IPAD-Pro meta CASE tool (see http://www.xcprod.com ). This
tool allows you to build fully interactive visual programming CASE tools for
niche markets or in-house use. The interface that allows you to build these
tools is itself also a fully interactive visual programming tool built using
IPAD-Pro. It allows you to quickly and easily build dialogs and controls
using the same kind of drag and drop approach as visual basic. ZMech (an
interactive state machine development system) is built using IPAD-Pro (a PIC
version of which is also available). And guess what, all this uses the power
and flexibility of pointers to methods.
>
> Basically, it only looks convoluted until you need to implement some extra
> functionality, then it makes it really easy and neat.
>
> Should we move this to [OT]?
>
I don't know that there is much more I can really say about this.
part 1 9039 bytes content-type:text/plain; (decoded 7bit)
Hi Sergio,
> We should firstly show the onlooker one of the aspects that
> was bothering me when I said I thought it was too convoluted.
> That is, your switch can handle either an ON condition or an
> OFF condition. It cannot handle both. To do so you would need
> to add another intermediate messaging class LightOffCommand
> (if we follow your previous naming convention). Your lamp
> would need to know whether it is currently on and ignore
> requests to turn on or whether it is currently off and
> ignore requests to turn off. A real switch cannot be
> turned on if it is already on, or off if it is already off.
> So to model the switch accurately you would have to build the logic into
> the switch not the lamp (as I have in fact done).
Oh, sorry, I was purposely just keeping the example as simple as I could to
get the idea of using the pattern across. My fault, I'm probably not
explaining this too well :)
Yes the switch would know its state and only turn "on" when it is "off". As
your code did. It would hold two Commands, a "LightOnCommand" and a
"LightOffCommand".
> If we have a motor with three input levels on it I would want
> it to be a different motor to one that only has an off/on input.
> I would only have a problem with the motor class if I tried to
> keep all my options open by adding on, off, left, mid, right,
> up, down, sideways, insideout blah blah blah to a motor base
> class. By using pointers to methods you can point to a
> method in one class that does not exist in another class and
> visa versa.
I agree about not polluting the base class. Again, I don't think I explained
that very well.
I was trying to show a way that you could deal with a more "analogue" value.
One that would be parameterised. The example was probably not that strong. I
was thinking along the lines of a servo motor system - the motor would have
a range of positions. It makes no sense to have a function for each of these
positions on your motor class, rather to have a single method to set a
position.
Lets say for arguments sake, that this is a simple CNC mill. The position of
the servo is important throughout the entire program and would be controlled
by the "SetPosition()" method when the machine is active.
This is a somewhat contrived example, I would actually model this
differently in a real system, but the purpose here is to demonstrate the
Command Pattern, not a "complete" system.
Now, we want to attach an operator interface so they can manually move
things around and move the tool onto and off of the work piece.
So, we want to implement the following commands with switches (or buttons
where only the press is important in this case, just to make the example a
little simpler).
- "Home" - move the X and Y servos to (0,0). Perhaps this is so the tool can
be changed by the operator
- "Center" - move the X and Y servos to (100, 100).
- "Step Left" (X axis)
- "Step Right" (X axis)
- "Step Forward" (Y axis)
- "Step Back" (Y axis)
From my perspective, it would be inelegant to implement a function for each
of these on the ServoMotor. And perhaps the "Home" position is arbitrary and
changes lots - the ServoMotor shouldn't care about where that really is, it
should be just managing the motor and going where it is told. Otherwise you
are introducing unnecessary dependency on other parts of the system into the
ServoMotor class (so it can find where home is).
Refer to the attached C++ file. Note I've put most of the functions in the
class definitions, but I would normally not do this. It is just for brevity.
This neatly (in my opinion) separates the "button" which is part of the user
interface from the servo motors which are part of the main program so there
is absolutely no coupling between them. This means that we are free to
change either without needing to look at the other.
In both the methods for handling the commands, code needs to be written that
knows what to do to the target. the Command Pattern places this code in
reusable classes which are bound only to the public interface of the servo
motor. Therefore the implementation of the servo motor is free to change
without affecting anything else.
Note also that the are two "generic" commands implemented, the
"SetPositionCommand" and the "StepCommand". These two are used for each of
the 6 different commands.
Not shown in this example is the CNC Milling Command interpreter. The cool
thing (I think) about the Command Pattern in this case is the interpreter
can be written to use exactly the same Commands (SetPositionCommand,
StepCommand) as the interface.
Or more to the point, the Interpreter would define a series of useful
Commands that would be reused in the interface. Then the code to manage the
movement is located in only one place - the concrete implementation of each
command-derived class.
Then at any stage, you can add new commands to the interpreter or the
interface and the other system can utilise them easily.
Also, see how easy it is to produce a macro that will execute and arbitrary
sequence of commands. This could be useful for interface buttons and in the
CNC command interpreter as it will allow the construction of complex
commands from previously implemented simple commands, again saving rewriting
code.
The MacroCommand was implemented using the standard template library's list
template just for convenience, it could be handled any way.. But why
reinvent the wheel? :)
> Provided you apply the method to the right type of object there is no
> conflict, and you certainly don't have to worry about
> propagating virtual
> methods all over the place.
>
> sw1->attach(m1, &MOTOR_ONE_SPEED::on);
>
> sw2->attach(m2, &MOTOR_TWO_SPEED::on);
> sw3->attach(m2, &MOTOR_TWO_SPEED::high);
This is one of my problems with the pointer mechanism - you are able to
accidentally specify the wrong object and the compiler will happily take
your word for it and crash. You loose the nice type safety that is provided
by the C++ compiler and this is not a thing to take lightly.
Also, there is nothing wrong with virtual method calls, sure there is
marginally more overhead, but we're talking about a user interface here, you
will never notice it. They are central to the way objects work in C++..
> I think the problem here is that you are locked into the
> virtual method mode of thinking. In which you have a pointer
> to a base class and you want to apply a method to an object
> of a derived class. You see the only way to
> access the method is by having a virtual instance in the
> base. Naturally all overloaded methods must take the same
> parameters. BUT if you scrub the virtual method and point
> directly to the real method, then the name becomes
> just a label AND two methods with the same name in two
> different classes CAN have different parameters and be
> accessed via a pointer to method without conflict.
And this is where I think we are going to disagree. I accept that your
method works and is a valid solution BUT if I was writing an application I
would rather avoid it. I think that you are locked into the "C" way of doing
"call-backs" and are not taking full advantage of the language features in
C++. Let us agree to disagree :)
However I feel the entire point of C++ is the virtual method / inheritance /
overriding / etc paradigm. When I write software, I want to use C++ BECAUSE
of these things - I don't see them as a hindrance that needs to be worked
around.
I want my code to be type safe to prevent mistakes like calling the function
on the wrong object. I want to have the simplest interfaces on objects, and
ensure that each object is a simple as it can be so they are easy to test
and verify. I want the various modules of code as well decoupled as possible
so that I can take code and reuse it in both the same program and in others.
Now, please don't take this as me saying: "This is the right way, and the
only way". I'm not saying that at all, I'm just illustrating an alternative
system which I think has some benefits over the pointers to member functions
method.
One other point - the Command pattern can be implemented in OO languages
that don't support pointers, like Java and Smalltalk etc. Not that I would
be writing in them :)
> > Should we move this to [OT]?
> >
> I don't know that there is much more I can really say about this.
Fair enough, I thank you for the discussion - I enjoyed it.