Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > polymorphic base class pointers and template classes

Reply
Thread Tools

polymorphic base class pointers and template classes

 
 
awm129
Guest
Posts: n/a
 
      06-07-2009
I have a need to wrap several different (related) legacy structures in
thier own classes. This seems to scream template classes with the
structure type as a template parameter for the creation of a private
class member of the templated type.

Now, I would also like to use a polymorphic base class pointer with
this family of classes (for use with a factory) as well as include
some common functionallity in a base class. I would also like to
force the inclusion of this templated private member for each derived
class. This seems increadibly simple but I can't seem to quite wrap
my head around how this would work. I want to do something simlar to
this:

//
// base class to implement common functionallity
//
template<class T>
class Base
{
virtual T wrappedStruct = 0;
void foo();
}

//
// derived classes
//
template<class T>
class D1 : Base<T>
{
T wrappedStruct;
}

int main()
{
// assume Bar is a structure type
Bar s;

// now I want to use a polymorphic pointer to manage these things
Base* ptr = DFactory( s );
}


I dont think I can create an "untyped" (eg. without the <Type>) Base
pointer, but then how do I get my polymorphism to work? Does any of
this make sense? Any ideas? Thanks!



 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      06-07-2009
* awm129:
> I have a need to wrap several different (related) legacy structures in
> thier own classes. This seems to scream template classes with the
> structure type as a template parameter for the creation of a private
> class member of the templated type.
>
> Now, I would also like to use a polymorphic base class pointer with
> this family of classes (for use with a factory) as well as include
> some common functionallity in a base class. I would also like to
> force the inclusion of this templated private member for each derived
> class. This seems increadibly simple but I can't seem to quite wrap
> my head around how this would work. I want to do something simlar to
> this:
>
> //
> // base class to implement common functionallity
> //
> template<class T>
> class Base


This would create a family of distinct base classes.


> {
> virtual T wrappedStruct = 0;


C++ does not support virtual data.


> void foo();


What's this for?


> }


Missing semicolon.

Did you intend for Base to have only private (inaccessible) members?



> //
> // derived classes
> //
> template<class T>
> class D1 : Base<T>
> {
> T wrappedStruct;
> }



>
> int main()
> {
> // assume Bar is a structure type
> Bar s;
>
> // now I want to use a polymorphic pointer to manage these things
> Base* ptr = DFactory( s );


Why do you want that?

What is the common functionality for the classes?


> }
>
>
> I dont think I can create an "untyped" (eg. without the <Type>) Base
> pointer, but then how do I get my polymorphism to work? Does any of
> this make sense? Any ideas? Thanks!


You could always use multiple inheritance, like

struct Base
{
virtual ~Base() {}
// whatever
};

struct MyLegacyClass: Base, LegacyClass
{
// Whatever
};

However, it may be a disservice to you to suggest anything at all, because while
you've described roughly a kind of technical solution, you haven't really
described the problem that this solution was meant to solve, in particular what
the object factory is meant to solve (and the object factory seems to the reason
for the wrapping, so if there's a better solution than the factory, which there
might well be, depending on what the problem is, then ignore the above).


Cheers & hth.,

- Alf


--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! Just going there is good. Linking
to it is even better! Thanks in advance!
 
Reply With Quote
 
 
 
 
awm129@gmail.com
Guest
Posts: n/a
 
      06-07-2009
On Jun 7, 2:16*am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * awm129:
>
>
>
>
>
> > I have a need to wrap several different (related) legacy structures in
> > thier own classes. *This seems to scream template classes with the
> > structure type as a template parameter for the creation of a private
> > class member of the templated type.

>
> > Now, I would also like to use a polymorphic base class pointer with
> > this family of classes (for use with a factory) as well as include
> > some common functionallity in a base class. *I would also like to
> > force the inclusion of this templated private member for each derived
> > class. *This seems increadibly simple but *I can't seem to quite wrap
> > my head around how this would work. *I want to do something simlar to
> > this:

>
> > //
> > // base class to implement common functionallity
> > //
> > template<class T>
> > class Base

>
> This would create a family of distinct base classes.
>
> > {
> > * virtual T wrappedStruct = 0;

>
> C++ does not support virtual data.


Yep, this was more to emphasize my desire to force derived classes to
have a member of the template type, I realize its not legal C++

>
> > * void foo();

>
> What's this for?


so, rename foo() (and taht should be public: void foo() to public:
void writeMessageToDatabase()

>
> > }

>
> Missing semicolon.
>
> Did you intend for Base to have only private (inaccessible) members?
>


no they will be at least protected, I seem to have omitted all
accessibility modifiers

>
>
>
>
> > //
> > // derived classes
> > //
> > template<class T>
> > class D1 : Base<T>
> > {
> > * T wrappedStruct;
> > }

>
> > int main()
> > {
> > * // assume Bar is a structure type
> > * Bar s;

>
> > * // now I want to use a polymorphic pointer to manage these things
> > * Base* ptr = DFactory( s );

>
> Why do you want that?


See below

>
> What is the common functionality for the classes?


The common functionality would be logging, printing, writting to a
database, etc

>
> > }

>
> > I dont think I can create an "untyped" (eg. without the <Type>) Base
> > pointer, but then *how do I get my polymorphism to work? *Does any of
> > this make sense? *Any ideas? *Thanks!

>
> You could always use multiple inheritance, like
>
> * * struct Base
> * * {
> * * * * virtual ~Base() {}
> * * * * // whatever
> * * };
>
> * * struct MyLegacyClass: Base, LegacyClass
> * * {
> * * * * // Whatever
> * * };


Multiple inheritence might be what I need

>
> However, it may be a disservice to you to suggest anything at all, because while
> you've described roughly a kind of technical solution, you haven't really
> described the problem that this solution was meant to solve, in particular what
> the object factory is meant to solve (and the object factory seems to the reason
> for the wrapping, so if there's a better solution than the factory, which there
> might well be, depending on what the problem is, then ignore the above).
>
> Cheers & hth.,
>
> - Alf
>
> --
> Due to hosting requirements I need visits to <url:http://alfps.izfree.com/>.
> No ads, and there is some C++ stuff! Just going there is good. Linking
> to it is even better! Thanks in advance!- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -



Thanks for the response! Here is a bit more background on what I'm
trying to do:

These legacy structures are a bunch of different messages. I'm
reading these off a pipe and they come in randomly. I want to pass
these to a factory to create the correct type of object and then I
want to pass these messages to several different handlers. These
handlers should only process the messages for which they are
interested in and just ignore the others. I had planned to have each
handler inherit from a base handler that knows how to process the
generic message type (type Base in my example above). Each derived
handler would have overloaded processing methods for the message types
that they are interested in. That way I can call Process( Base* s )
on a derived handler and all generic messages are passed through while
certain message types are caught and processed by an overloaded form
of Process() in the derived handler. The only place the messages need
to be handled differently based on type is inside the handlers, I want
to treat them gernerically outside the handlers; thus my desire for a
base class pointer. This may be easier to see with more psudo code,
but I can't post any at the moment. Does this clarify my intents at
all? Thanks again.
 
Reply With Quote
 
Bart van Ingen Schenau
Guest
Posts: n/a
 
      06-08-2009
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> Thanks for the response! Here is a bit more background on what I'm
> trying to do:
>
> These legacy structures are a bunch of different messages. I'm
> reading these off a pipe and they come in randomly. I want to pass
> these to a factory to create the correct type of object and then I
> want to pass these messages to several different handlers. These
> handlers should only process the messages for which they are
> interested in and just ignore the others. I had planned to have each
> handler inherit from a base handler that knows how to process the
> generic message type (type Base in my example above). Each derived
> handler would have overloaded processing methods for the message types
> that they are interested in. That way I can call Process( Base* s )
> on a derived handler and all generic messages are passed through while
> certain message types are caught and processed by an overloaded form
> of Process() in the derived handler. The only place the messages need
> to be handled differently based on type is inside the handlers, I want
> to treat them gernerically outside the handlers; thus my desire for a
> base class pointer. This may be easier to see with more psudo code,
> but I can't post any at the moment. Does this clarify my intents at
> all? Thanks again.


Yes, it does clarify. And it also gives an opportunity to point out that
your design has a few pitfalls you need to look out for.
The first one is that overload resolution is done on the *static* (or
declared) type. In order to be able to call the correct overload of the
processing functions, if you only have a pointer to the base class
available, you need a double-dispatch mechanism.

See the output from this program for what I mean:

#include <iostream>
using namespace std;

struct MessageA {};
struct MessageB {};

class MessageBase;
template <class T> class Message;

void Process(const MessageBase*);
void Process(const Message<MessageA>*);

class MessageBase
{
public:
virtual ~MessageBase() {}
virtual void call_Process() = 0;
};

template <class T>
class Message : public MessageBase, public T
{
Message() : MessageBase(), T() {}

public:
virtual void call_Process()
{
Process(this);
}
static Message<T>* create() { return new Message<T>(); }
};

void Process(const MessageBase*)
{
cout << " Process(const MessageBase*)" << endl;
}

void Process(const Message<MessageA>*)
{
cout << " Process(const Message<MessageA>*)" << endl;
}

int main()
{
MessageBase* message1 = Message<MessageA>::create();
MessageBase* message2 = Message<MessageB>::create();

cout << "Calling \"Process\" directly" << endl;
Process(message1);
Process(message2);

cout << "Calling \"Process\" indirectly" << endl;
message1->call_Process();
message2->call_Process();
}

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

 
Reply With Quote
 
awm129@gmail.com
Guest
Posts: n/a
 
      06-09-2009
On Jun 8, 2:35*pm, Bart van Ingen Schenau <(E-Mail Removed)>
wrote:
> (E-Mail Removed) wrote:
> > Thanks for the response! *Here is a bit more background on what I'm
> > trying to do:

>
> > These legacy structures are a bunch of different messages. *I'm
> > reading these off a pipe and they come in randomly. *I want to pass
> > these to a factory to create the correct type of object and then I
> > want to pass these messages to several different handlers. *These
> > handlers should only process the messages for which they are
> > interested in and just ignore the others. *I had planned to have each
> > handler inherit from a base handler that knows how to process the
> > generic message type (type Base in my example above). *Each derived
> > handler would have overloaded processing methods for the message types
> > that they are interested in. *That way I can call Process( Base* s )
> > on a derived handler and all generic messages are passed through while
> > certain message types are caught and processed by an overloaded form
> > of Process() in the derived handler. *The only place the messages need
> > to be handled differently based on type is inside the handlers, I want
> > to treat them gernerically outside the handlers; thus my desire for a
> > base class pointer. *This may be easier to see with more psudo code,
> > but I can't post any at the moment. *Does this clarify my intents at
> > all? *Thanks again.

>
> Yes, it does clarify. And it also gives an opportunity to point out that
> your design has a few pitfalls you need to look out for.
> The first one is that overload resolution is done on the *static* (or
> declared) type. In order to be able to call the correct overload of the
> processing functions, if you only have a pointer to the base class
> available, you need a double-dispatch mechanism.
>
> See the output from this program for what I mean:
>
> #include <iostream>
> using namespace std;
>
> struct MessageA {};
> struct MessageB {};
>
> class MessageBase;
> template <class T> class Message;
>
> void Process(const MessageBase*);
> void Process(const Message<MessageA>*);
>
> class MessageBase
> {
> public:
> * virtual ~MessageBase() {}
> * virtual void call_Process() = 0;
>
> };
>
> template <class T>
> class Message : public MessageBase, public T
> {
> * Message() : MessageBase(), T() {}
>
> public:
> * virtual void call_Process()
> * {
> * * Process(this);
> * }
> * static Message<T>* create() { return new Message<T>(); }
>
> };
>
> void Process(const MessageBase*)
> {
> * cout << " *Process(const MessageBase*)" << endl;
>
> }
>
> void Process(const Message<MessageA>*)
> {
> * cout << " *Process(const Message<MessageA>*)" << endl;
>
> }
>
> int main()
> {
> * MessageBase* message1 = Message<MessageA>::create();
> * MessageBase* message2 = Message<MessageB>::create();
>
> * cout << "Calling \"Process\" directly" << endl;
> * Process(message1);
> * Process(message2);
>
> * cout << "Calling \"Process\" indirectly" << endl;
> * message1->call_Process();
> * message2->call_Process();
>
> }
>
> Bart v Ingen Schenau
> --
> a.c.l.l.c-c++ FAQ:http://www.comeaucomputing.com/learn/faq
> c.l.c FAQ:http://c-faq.com/
> c.l.c++ FAQ:http://www.parashift.com/c++-faq-lite/


On Jun 8, 2:35 pm, Bart van Ingen Schenau <(E-Mail Removed)>
wrote:
> (E-Mail Removed) wrote:
> > Thanks for the response! Here is a bit more background on what I'm
> > trying to do:

>
> > These legacy structures are a bunch of different messages. I'm
> > reading these off a pipe and they come in randomly. I want to pass
> > these to a factory to create the correct type of object and then I
> > want to pass these messages to several different handlers. These
> > handlers should only process the messages for which they are
> > interested in and just ignore the others. I had planned to have each
> > handler inherit from a base handler that knows how to process the
> > generic message type (type Base in my example above). Each derived
> > handler would have overloaded processing methods for the message types
> > that they are interested in. That way I can call Process( Base* s )
> > on a derived handler and all generic messages are passed through while
> > certain message types are caught and processed by an overloaded form
> > of Process() in the derived handler. The only place the messages need
> > to be handled differently based on type is inside the handlers, I want
> > to treat them gernerically outside the handlers; thus my desire for a
> > base class pointer. This may be easier to see with more psudo code,
> > but I can't post any at the moment. Does this clarify my intents at
> > all? Thanks again.

>
> Yes, it does clarify. And it also gives an opportunity to point out that
> your design has a few pitfalls you need to look out for.
> The first one is that overload resolution is done on the *static* (or
> declared) type. In order to be able to call the correct overload of the
> processing functions, if you only have a pointer to the base class
> available, you need a double-dispatch mechanism.
>
> See the output from this program for what I mean:
>
> #include <iostream>
> using namespace std;
>
> struct MessageA {};
> struct MessageB {};
>
> class MessageBase;
> template <class T> class Message;
>
> void Process(const MessageBase*);
> void Process(const Message<MessageA>*);
>
> class MessageBase
> {
> public:
> virtual ~MessageBase() {}
> virtual void call_Process() = 0;
>
> };
>
> template <class T>
> class Message : public MessageBase, public T
> {
> Message() : MessageBase(), T() {}
>
> public:
> virtual void call_Process()
> {
> Process(this);
> }
> static Message<T>* create() { return new Message<T>(); }
>
> };
>
> void Process(const MessageBase*)
> {
> cout << " Process(const MessageBase*)" << endl;
>
> }
>
> void Process(const Message<MessageA>*)
> {
> cout << " Process(const Message<MessageA>*)" << endl;
>
> }
>
> int main()
> {
> MessageBase* message1 = Message<MessageA>::create();
> MessageBase* message2 = Message<MessageB>::create();
>
> cout << "Calling \"Process\" directly" << endl;
> Process(message1);
> Process(message2);
>
> cout << "Calling \"Process\" indirectly" << endl;
> message1->call_Process();
> message2->call_Process();
>
> }
>
> Bart v Ingen Schenau
> --
> a.c.l.l.c-c++ FAQ:http://www.comeaucomputing.com/learn/faq
> c.l.c FAQ:http://c-faq.com/
> c.l.c++ FAQ:http://www.parashift.com/c++-faq-lite/


Excellent point! I had assumed some sort of special processing would
be needed in the handlers to get to the correct overload, but this
illustrates the point quite clearly. I didn't think about overload
resolution being based on the static type... This may throw my design
out the window altogether.

As a side note, I ended up abandoning templates for the derived
classes. It turns out each and every message type would need its own
specialization anyway which kinda defeats the point of the templates.
So now I have 20 some odd similar yet different message classes.

I want this, but I don't think it can work (forgive any typos as I
don't have a compiler on this machine):


struct LegacyMessageA {};

class MessageBase
{
public:
virtual ~MessageBase() {}
};

class MessageA : public MessageBase
{
public:
MessageA(const MessageA msg) : MessageBase() //assume msg is copied
to m_msg
// assume accessors into m_msg
// assume common functionality for all messages
private:
LegacyMessageA m_msg
};

class HandlerBase
{
public:
HandlerBase(){}
virtual ~HandlerBase(){}
void process( MessageBase* msg );
protected:
void _doProcess( MessageBase* msg );
};

HandlerBase:rocess( MessageBase* msg )
{
// this is only ever going to call _doProcess( MessageBase* msg )
// as opposed to the proper overload for the actual type of msg.
// I want it to call the proper overload in the derived handler!

this->_doProcess( msg )
}

HandlerBase::_doProcess( MessageBase* msg )
{
//do nothing
}

class MessageAHandler : HandlerBase
{
public:
DerivedHandler() : HandlerBase() {}
private:
_doProcess( MessageA* msg );
};

MessageAHandler::_doProcess( MessageA* msg )
{
// special handling for type MessageA.
// I don't think this ever gets called as all messages go
// to MessageBase::_doProcess( MessageBase* msg )
}

int main()
{
LegacyMessageA msg;
MessageBase* message1 = new MessageA( msg );
HandlerBase* handler = new MessageAHandler();

handler->process( message1 );

delete message1;
delete handler;

return 0;
}


Can this scheme work at all? It all seemed so elegant yesterday!

 
Reply With Quote
 
Bart van Ingen Schenau
Guest
Posts: n/a
 
      06-10-2009
(E-Mail Removed) wrote:

> Excellent point! I had assumed some sort of special processing would
> be needed in the handlers to get to the correct overload, but this
> illustrates the point quite clearly. I didn't think about overload
> resolution being based on the static type... This may throw my design
> out the window altogether.
>
> As a side note, I ended up abandoning templates for the derived
> classes. It turns out each and every message type would need its own
> specialization anyway which kinda defeats the point of the templates.
> So now I have 20 some odd similar yet different message classes.
>
> I want this, but I don't think it can work (forgive any typos as I
> don't have a compiler on this machine):


It can work. Look up the Visitor design pattern, which is basically what
you need to implement.
It helps if you have an unchanging set of Message classes, which you
seem to have.

>
>
> struct LegacyMessageA {};
>

You need a forward declaration of HandlerBase:
class HandlerBase;

> class MessageBase
> {
> public:
> virtual ~MessageBase() {}

Here you need a pure-virtual function to make a 'call back' to the
handler:
virtual void call_doProcess(HandlerBase*) = 0;
> };
>
> class MessageA : public MessageBase
> {
> public:
> MessageA(const MessageA msg) : MessageBase() //assume msg is copied
> to m_msg
> // assume accessors into m_msg
> // assume common functionality for all messages

Each concrete Message class must implement the call_doProcess to call
that function in the handler:
virtual void call_doProcess(HandlerBase* handler);

> private:
> LegacyMessageA m_msg
> };
>
> class HandlerBase
> {
> public:
> HandlerBase(){}
> virtual ~HandlerBase(){}
> void process( MessageBase* msg );
> protected:

HandlerBase must have the _doProcess functions public (unless you want
to juggle with friend declarations) and provide a default implementation
for each concrete Message class:
public:
virtual void _doProcess( MessageBase* msg );
virtual void _doProcess( MessageA* msg)
{ _doProcess(static_cast<MessageBase*>(msg)); }
> };
>
> HandlerBase:rocess( MessageBase* msg )
> {
> // this is only ever going to call _doProcess( MessageBase* msg )
> // as opposed to the proper overload for the actual type of msg.
> // I want it to call the proper overload in the derived handler!
>

Here you must ask the message to call _doProcess for you:
msg->call_doProcess(this);

> this->_doProcess( msg )
> }
>
> HandlerBase::_doProcess( MessageBase* msg )
> {
> //do nothing
> }


Implementation for the call_doProcess function can come here:
void MessageA::call_doProcess(HandlerBase* handler)
{
handler->_doProcess(this);
}

>
> class MessageAHandler : HandlerBase
> {
> public:
> DerivedHandler() : HandlerBase() {}
> private:
> _doProcess( MessageA* msg );
> };
>
> MessageAHandler::_doProcess( MessageA* msg )
> {
> // special handling for type MessageA.
> // I don't think this ever gets called as all messages go
> // to MessageBase::_doProcess( MessageBase* msg )


As this now overrides a function of the base class, it can get called by
MessageA::call_doProcess.

> }
>
> int main()
> {
> LegacyMessageA msg;
> MessageBase* message1 = new MessageA( msg );
> HandlerBase* handler = new MessageAHandler();
>
> handler->process( message1 );
>
> delete message1;
> delete handler;
>
> return 0;
> }
>
>
> Can this scheme work at all? It all seemed so elegant yesterday!


Yes. With the changes I indicated it becomes a bit less elegant (the
HandlerBase must know about all the specific messages), but it will
work.

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

 
Reply With Quote
 
awm129@gmail.com
Guest
Posts: n/a
 
      06-10-2009
On Jun 10, 4:23*am, Bart van Ingen Schenau <(E-Mail Removed)>
wrote:
> (E-Mail Removed) wrote:
> > Excellent point! *I had assumed some sort of special processing would
> > be needed in the handlers to get to the correct overload, but this
> > illustrates the point quite clearly. *I didn't think about overload
> > resolution being based on the static type... This may throw my design
> > out the window altogether.

>
> > As a side note, I ended up abandoning templates for the derived
> > classes. *It turns out each and every message type would need its own
> > specialization anyway which kinda defeats the point of the templates.
> > So now I have 20 some odd similar yet different message classes.

>
> > I want this, but I don't think it can work (forgive any typos as I
> > don't have a compiler on this machine):

>
> It can work. Look up the Visitor design pattern, which is basically what
> you need to implement.
> It helps if you have an unchanging set of Message classes, which you
> seem to have.
>
>
>
> > struct LegacyMessageA {};

>
> You need a forward declaration of HandlerBase:
> *class HandlerBase;
>
> > class MessageBase
> > {
> > public:
> > * virtual ~MessageBase() {}

>
> Here you need a pure-virtual function to make a 'call back' to the
> handler:
> * * virtual void call_doProcess(HandlerBase*) = 0;> };
>
> > class MessageA : public MessageBase
> > {
> > public:
> > * MessageA(const MessageA msg) : MessageBase() *//assume msg is copied
> > to m_msg
> > * // assume accessors into m_msg
> > * // assume common functionality for all messages

>
> Each concrete Message class must implement the call_doProcess to call
> that function in the handler:
> * * virtual void call_doProcess(HandlerBase* handler);
>
> > private:
> > * LegacyMessageA m_msg
> > };

>
> > class HandlerBase
> > {
> > public:
> > * HandlerBase(){}
> > * virtual ~HandlerBase(){}
> > * void process( MessageBase* msg );
> > protected:

>
> HandlerBase must have the _doProcess functions public (unless you want
> to juggle with friend declarations) and provide a default implementation
> for each concrete Message class:
> * public:
> * * virtual void _doProcess( MessageBase* msg );
> * * virtual void _doProcess( MessageA* msg)
> * * { _doProcess(static_cast<MessageBase*>(msg)); }> };
>
> > HandlerBase:rocess( MessageBase* msg )
> > {
> > * // this is only ever going to call _doProcess( MessageBase* msg )
> > * // as opposed to the proper overload for the actual type of msg.
> > * // I want it to call the proper overload in the derived handler!

>
> Here you must ask the message to call _doProcess for you:
> * * msg->call_doProcess(this);
>
> > * this->_doProcess( msg )
> > }

>
> > HandlerBase::_doProcess( MessageBase* msg )
> > {
> > * //do nothing
> > }

>
> Implementation for the call_doProcess function can come here:
> void MessageA::call_doProcess(HandlerBase* handler)
> {
> * handler->_doProcess(this);
>
> }
>
> > class MessageAHandler : HandlerBase
> > {
> > * public:
> > * * DerivedHandler() : HandlerBase() {}
> > * private:
> > * * _doProcess( MessageA* msg );
> > };

>
> > MessageAHandler::_doProcess( MessageA* msg )
> > {
> > * // special handling for type MessageA.
> > * // I don't think this ever gets called as all messages go
> > * // to MessageBase::_doProcess( MessageBase* msg )

>
> As this now overrides a function of the base class, it can get called by
> MessageA::call_doProcess.
>
>
>
> > }

>
> > int main()
> > {
> > * LegacyMessageA msg;
> > * MessageBase* message1 = new MessageA( msg );
> > * HandlerBase* handler = new MessageAHandler();

>
> > * handler->process( message1 );

>
> > * delete message1;
> > * delete handler;

>
> > * return 0;
> > }

>
> > Can this scheme work at all? *It all seemed so elegant yesterday!

>
> Yes. With the changes I indicated it becomes a bit less elegant (the
> HandlerBase must know about all the specific messages), but it will
> work.
>
> Bart v Ingen Schenau
> --
> a.c.l.l.c-c++ FAQ:http://www.comeaucomputing.com/learn/faq
> c.l.c FAQ:http://c-faq.com/
> c.l.c++ FAQ:http://www.parashift.com/c++-faq-lite/



I had never heard of the visitor design pattern and it seems to very
much fit what I want to do. I had resigned myself to using RTTI and a
giant switch in HandlerBase but I like the double dispatch through the
Message much much better. Thank you very much for the help and
suggestions, I'm looking forward to getting this thing implemented!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
polymorphic call via this pointer stored in base class constructor andy_P C++ 4 11-15-2010 07:51 AM
base class public type (non template and template base class) Hicham Mouline C++ 1 04-20-2009 03:28 PM
r H2 deduce deduce template argument of a template class inheritingfrom a non template base? nguillot C++ 5 03-08-2009 05:56 PM
Template specialisation of class with base class template ?! Tim Clacy C++ 12 12-03-2003 05:51 PM
Re: template class derived from non-template base class Matt Graham C++ 0 07-21-2003 09:02 PM



Advertisments