* Shaun:
My C++ is a bit rusty. Here's what I'm attempting to do:
class Cmd { };
class CmdA : public Cmd { };
class CmdB : public Cmd { };
...
Cmd *a = new CmdA ();
Cmd *b = new CmdB ();
First problem:
cout << typeid (a).name ()
cout << typeid (b).name ()
both return Cmd * types.
My desired result is CmdA* and CmdB*. Any
way of accomplishing this other than:
if (dynamic_cast <CmdA *> (a)) ...
The dynamic_cast wouldn't work either, but it's more on the right track.
For the dynamic_cast to work the statically known type Cmd needs to have at
least one virtual member routine, e.g. a virtual destructor suffices, and we
then say that Cmd is a "polymorphic type".
For the typeid expressions you'd need to check the typeid's of the referenced
objects, e.g. typeid(*a). Note, in passing (it's always fun to consider such
counter-intuitive details of the C++ language specification) that typeid is the
only place in C++ where you can dereference a nullpointer without Undefined
Behavior. That's because it's not really a function call but an operator that
the compiler translates to magic.
Second, I would like to do something like this:
class Target {
public:
void handleCommand (Cmd *c) { cout << "generic
command..." }
void handleCommand (CmdA *a) { cout << "Cmd A"; }
void handleCommand (CmdB *b) { cout << "Cmd B"; }
};
Target t;
t.handleCommand (a);
t.handleCommand (b);
and get the output "Cmd A" and "Cmd B". Right now it prints out
"generic command..." twice.
Yeah, what you're looking for is called the "visitor pattern".
There are umpteen ways to do it, differing in what types know about what. If you
can assume that all Cmd derived types are known up front at the place of
definition of Target, then you can do it /without any casting/. It's very nice,
but, repeat, the cast-free version requires knowledge of all derived classes:
// Disclaimer: off-the-cuff code.
class Cmd;
class CmdA;
class CmdB;
class Target;
class Target
{
public:
void handle( Cmd const& ) { cout << "generic command..."; }
void handle( CmdA const& ) { cout << "Cmd A"; }
void handle( CmdB const& ) { cout << "Cmd B"; }
};
class Cmd
{
public:
virtual ~Cmd() {}
virtual void callHandlerOn( Target& t )
{
t.handle( *this );
}
};
class CmdA: public Cmd
{
public:
virtual void callHandlerOn( Target& t )
{
t.handle( *this );
}
};
class CmdB: public Cmd
{
public:
virtual void callHandlerOn( Target& t )
{
t.handle( *this );
}
};
The apparently identical repeated code in CmdA and CmdB isn't really identical,
because the statically known type of '*this* differs...
And the general idea here is that, regardless of programming language, a virtual
call of a method does a downcast for you (namely of the 'this' pointer in C++),
in a type safe manner.
If you can't assume that all derived classes are known at the place of
definition of Target, then you need some explicit cast, like dynamic_cast, and
the main idea is then to centralize that in the method I've called
'callHandlerOn' above. Any command object then knows its own type, and tries to
downcast the Target argument to an interface that supports that self-type, and
if there's no such interface, using more general Target functionality.
Cheers & hth.,
- Alf