views:

264

answers:

4

hi, I have a weird issue using polymorphism. I have a base class that implements a static method. This method must be static for various reasons. The base class also has a pure virtual method run() that gets implemented by all the extended classes. I need to be able to call run() from the static class.

The problem, of course, is that the static class doesn't have a this pointer. This method can be passed in a void * parameter. I have been trying to come up with a clever way to pass the run method into it, but nothing has worked so far. have also tried passing this into it. The problem with this is that I would then have to instantiate it, which requires knowledge of the extended class. This defeats the whole purpose of the polymorphism.

Any ideas on how to go about this?

+3  A: 

Why not pass a reference to the object in rather than the method e.g.

static void func( BaseObject& o)
{
     o.run();
}
Mark
+8  A: 

Don't pass it as a void* pointer, pass it as a pointer (or reference) to the base class:

class BaseClass
{
public:
  static void something(BaseClass* self) { self->foo(); }
  virtual void foo() = 0;  
};
ChrisW
+1  A: 

IMO, your best bet is to get rid of the static method. Find a way around that and you're golden.

Randolpho
+4  A: 

This usually happens when you have to squirrel your C++ objects through a C API. A classic example is a thread class.

Here's the standard idiom for doing this:

/** calls thread_func in a new thread passing it user_data as argument */
thrd_hdl c_api_thread_start(int (*thread_func)(void*), void* user_data);

/** abstract thread base class
* override my_thread::run to do work in another thread
*/
class my_thread {
  public:
    my_thread() hdl_(c_api_thread_start(my_thread::thread_runner,this)) {}
    // ...

  private:
    virtual int run() = 0; // we don't want this to be called from others

    thrd_hdl_t hdl_; // whatever the C threading API uses as a thread handle

    static int thread_runner(void* user_data)
    {
      my_thread* that = reinterpret_cast<my_thread*>(user_data);
      try {
        return that->run();
      } catch(...) {
        return oh_my_an_unknown_error;
      }
    }
};

Would that help?

sbi