views:

103

answers:

4

I have a base class MessageHandler and 2 derived classes, MessageHandler_CB and MessageHandler_DQ.

The derived classes redefine the handleMessage(...) method. MH_DQ processes a message and puts the result in a deque while MH_CB processes the message and then executes a callback function.

The base class has a static callback function that I pass along with a this pointer to a library which calls the static callback when a new message is available for processing.

My problem comes when I am in the static callback with a void * pointing to either a MH_DQ or a MH_CB. If I cast it to the base class the empty MessageHandler::handleMessage(...) method is called, rather than the version in the appropriate derived class.

What is the best way to address this situation from a design perspective and/or what language features might help me to implement a solution to my problem?

Thanks in advance!

Okay, the virtual method did not work like magic. There is a twist to the story. I have a static method in the base class and a pure virtual member function to handle the message processing, but I want to first call a member function in the pure virtual base class to preprocess the message before I route it to the derived class.

So I have :

class MH {

...

static int CallBackFunction(MessageData *md, void *this_ptr) {
  ((MH *)this_ptr)->preprocess(md);
  return 1;
}

virtual int preprocess(MessageData *md) {
  // do some stuff
  . . .

  handleMessage(md);
  return 1;
}

virtual void handleMessage(MessageData *) = 0;

};

class MH_CB : public MH {

...

void handleMessage(MessageData *md) {
  // do something
  ...
}
};

class MH_DQ : public MH {
...

void handleMessage(MessageData *md) {
  // do something different
  ...
}
};

Unfortunately, this code produces a run-time error that a pure virtual function is being called. Any thoughts?

TIA

+1  A: 

Make the original method call virtual.

wheaties
Thanks wheaties!
shaz
+1  A: 

Don't pass a void* in the callback - pass a pointer to the base class, and declare handleMessage to be virtual.

corvuscorax
+1  A: 

Add the virtual keyword to the declaration/definition of the method in the base class.

In fact if the method in the base class is never supposed to run then you can specify that it's pure virtual to declare it with no body at all, instead of defining an empty body:

class MessageHandler
{
public:
    virtual void handleMessage(...) = 0;
};
ChrisW
A: 

Mark the handleMessage() as virtual by prefixing void handleMessage() or whatever declaration in the base class with the word virtual. Then, make sure that the derived classes implement the exact same message signature (i.e. same return type and parameter types).

Also- instead of a void* use a MessageHandlerBase* (or whatever is appropriate). Then you don't need to cast. Casting is often the sign of a logic error on the part of the programmer.

dash-tom-bang