Roy Yao said:
The problem troubling me is that I must convert a virtual member function
pointer to a non-member function pointer
You cannot do this in C++.
in order that other modules can
call the virtual member function without an object( that is the "this"
pointer is not needed in my virtual member function).
First, a member function which does not use the "this" pointer should
not be a member function (or, at least, it should be a static member
function). Second, all virtual function calls use the "this" pointer
to determine which implementation to call.
As such, you can do what you want by breaking up the virtual function
into a static member function and a virtual function which calls it:
class Base {
public:
virtual void f () = 0;
virtual ~Base ();
};
class Derived : public Base {
public:
static void do_f ();
void f () { do_f(); }
};
Then pass &Derived::do_f instead.
However, that's not how you'd normally deal with a properly-written
C-style callback API. Such an API would take a pointer to a function
and a pointer to data to be passed to that function:
typedef void *cb_data_t;
typedef void (*cb_func_t) (cb_data_t);
void do_callback (cb_func_t f, cb_data_t x); /* calls f(x) */
To this API, pass a pointer to an object and a pointer to either a
static member or a non-member function which calls the desired member
function on the object:
class MyClass {
public:
void f ();
};
void call_f (cb_data_t p) { static_cast<MyClass *>(p)->f(); }
int main () {
MyClass obj;
do_callback(call_f, &obj);
return 0;
}
Note that you have to be really careful when you do this with
inheritance:
class Base {
public:
virtual void f () = 0;
virtual ~Base ();
};
void call_f (cb_data_t p) { static_cast<Base *>(p)->f(); }
class Derived : public Base {
public:
virtual void f ();
};
int main () {
Derived obj;
// WRONG: call_f expects Base *; we're passing Derived *
do_callback(call_f, &obj);
// RIGHT: pass Base * as expected
do_callback(call_f, static_cast<Base *>(&obj));
return 0;
}
In theory, conversion of Derived * to void * to Base * is undefined.
In practice, it probably will work unless multiple or virtual
inheritance is used. In any case, I suggest that you not take any
chances -- convert to Base * before passing. If you don't like casts
(who does?), you can write a wrapper like this instead:
// guarantees that x is a Base *
void do_base_callback (cb_func_t f, Base *x) { do_callback(f, x); }
int main () {
Derived obj;
do_base_callback(call_f, &obj);
return 0;
}
- Shane