By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,446 Members | 3,019 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,446 IT Pros & Developers. It's quick & easy.

How can I get the address of a virtual member function?

P: n/a
Hello,

I need to pass a pointer to a
callback function to the lower
level modules. But the function
is thought to be a virtual member one.

How can I get the real address of
the virtual member function?

Best regards,
Roy
Jul 19 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"Roy Yao" <fl***@263.net> wrote...
I need to pass a pointer to a
callback function to the lower
level modules. But the function
is thought to be a virtual member one.

How can I get the real address of
the virtual member function?


There is no difference of getting the address
of a member function based on its virtuality.
The way the address is used will determine
which function is actually called. The syntax
for getting the address of a member is

& <class-name> :: <member-name>

for example:

struct A {
virtual int foo() { return 42; }
};

struct B : A {
int foo() { return 73; }
};

int main() {
B b;
A& a = b;
int (A::*amem)() = &A::foo; // take address
return (a.*amem)(); // use the address
}

(the program above should return 73 to the hosting
environment)

BTW, what problem are you encountering?

Victor
Jul 19 '05 #2

P: n/a
Hello, Victor,

Thanks at first.

The problem troubling me is that I must convert a virtual member function
pointer to a non-member function pointer 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).

Can you catch my idea?

Roy

"Victor Bazarov" <v.********@attAbi.com> wrote in message
news:d%gdb.444108$cF.142132@rwcrnsc53...
"Roy Yao" <fl***@263.net> wrote...
I need to pass a pointer to a
callback function to the lower
level modules. But the function
is thought to be a virtual member one.

How can I get the real address of
the virtual member function?


There is no difference of getting the address
of a member function based on its virtuality.
The way the address is used will determine
which function is actually called. The syntax
for getting the address of a member is

& <class-name> :: <member-name>

for example:

struct A {
virtual int foo() { return 42; }
};

struct B : A {
int foo() { return 73; }
};

int main() {
B b;
A& a = b;
int (A::*amem)() = &A::foo; // take address
return (a.*amem)(); // use the address
}

(the program above should return 73 to the hosting
environment)

BTW, what problem are you encountering?

Victor

Jul 19 '05 #3

P: n/a
"Roy Yao" <fl***@263.net> wrote in message news:<bl***********@mail.cn99.com>...
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
Jul 19 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.