Member function pointer woes

A

Albert

Hi,

I need to pass a pointer-to-member-function as a parameter to a function
which takes pointer-to-function as an argument. Is there any way to do it
besides overloading the function?

Here is a small program I wrote to check if I could get the address of the
function from the member-function-pointer, so that I could pass it to the
function as a normal function-pointer.

---------------------------------------------------
#include<stdio.h>

class classname{
public:
int add(int a, int b){
printf("inside add. \ta = %d, b = %d\n", a,b);
return a+b;
}
}obj;


typedef int(classname::*mfptr)(int, int);
typedef int (*fptr)(int, int);


main(){

mfptr mem_func_ptr;
fptr func_ptr;

mem_func_ptr = &classname::add;
func_ptr = (fptr)(&classname::add);

printf("&classname::add is %llx\n", &classname::add);
printf("&classname::add is %llx\n", &classname::add);

printf("mem_func_ptr is %llx\n", mem_func_ptr);
printf("func_ptr is %x\n\n", func_ptr);

printf("add called with func_ptr. sum is %d\n\n", func_ptr(2,3));
printf("add called with mem_func_fptr. sum is %d\n\n",
(obj.*mem_func_ptr)(2,3));
}

-----------------------------------------------------


I compiled it with the -Wno-pmf-conversions option. Here is the output of
the program:

------------------------------------------
&classname::add is ffbeee78ff23e5d0
&classname::add is ffbeee78ff243a4c

mem_func_ptr is ffbeee78ff243a4c
func_ptr is 109bc

inside add. a = 3, b = 68028
add called with func_ptr. sum is 68031

inside add. a = 2, b = 3
add called with mem_func_fptr. sum is 5

------------------------------------------


A few questions:

1. Why is the value of '&classname::add' in the two lines different?
2. Why does the value of parameter 'b' change when 'classname::add' is
called with 'func_ptr'?
3. If this approach is not correct, then could you please advise as to how
to go about with it?

Thanks.

Albert.
 
J

John Harrison

Albert said:
Hi,

I need to pass a pointer-to-member-function as a parameter to a function
which takes pointer-to-function as an argument. Is there any way to do it
besides overloading the function?
No.

[snip]

3. If this approach is not correct, then could you please advise as to how
to go about with it?

Write a normal function which calls your member function and then pass the
normal function as a parameter.

john
 
M

Mark Warren

Albert said:
Hi,

I need to pass a pointer-to-member-function as a parameter to a
function which takes pointer-to-function as an argument. Is there any
way to do it besides overloading the function?

<snipped>

3. If this approach is not correct, then could you please advise as
to how to go about with it?

I would advise you to consider using the Boost.Function library.
http://www.boost.org/doc/html/function.html

I have used it to have a library function which can take pointer-to-function
or pointer-to-member-function in different programs.

Mark
 
L

LNK2005

Albert said:
I need to pass a pointer-to-member-function as a parameter to a function
which takes pointer-to-function as an argument. Is there any way to do it
besides overloading the function?


You could use a templated version of the subscriber/publisher pattern. The
implementation isn't pretty, but the usage is kind of neat IMHO;-) Note that
SubscriberBase and Subscriber can be reused for other notifications of the
same type (for any class), in this case member functions that take an int
and return void.

// Base class for Subscriber. Must be a non-template since we
// need to store a pointer to an instance.
class SubscriberBase
{
public:
virtual void exec(int) = 0;
};

// The actual Subscriber class template. Stores a pointer to an object and a
pointer
// to one of it's member functions.
template<class T> class Subscriber : public SubscriberBase
{
private:
typedef void (T::*EventFunc)(int);
T *target; // Pointer to the object to recieve notification
EventFunc func; // Pointer to member function to be called
public:
Subscriber(T *target, EventFunc func) : func(func), target(target) { }
virtual void exec(int param) { (target->*func)(param); }
};

// And this is how it's used.
// Class that does stuff and notifies another object about something...
class Publisher
{
protected:
SubscriberBase *sub; // Could be a list really
public:
void registerSubscriber(SubscriberBase &s)
{
sub = &s;
};
void doSomething(int param)
{
// Do something
// ...
sub->exec(param); // ... and notify
}
};

// Test class. Recieves notifications.
class UserClass
{
public:
// Starts the the entire thing
void start()
{
// Publisher object that needs to tell this instance of UserClass about
something
Publisher test;

// Construct and register a subscriber object.
Subscriber<UserClass> sub(this, callback);
test.registerSubscriber(sub);

// Call a function that sends back notifications
test.doSomething(12345);
}

// Callback member function
void callback(int param)
{
cout << "Hello, " << param << endl;
}
};
 
B

Bob Hairgrove

Hi,

I need to pass a pointer-to-member-function as a parameter to a function
which takes pointer-to-function as an argument. Is there any way to do it
besides overloading the function?

Here is a small program I wrote to check if I could get the address of the
function from the member-function-pointer, so that I could pass it to the
function as a normal function-pointer.

Better to use said:
class classname{
public:
int add(int a, int b){
printf("inside add. \ta = %d, b = %d\n", a,b);
return a+b;
}
}obj;
^^^
What is that? Is this legal C++?
typedef int(classname::*mfptr)(int, int);
typedef int (*fptr)(int, int);


main(){

Always return int from main()...
mfptr mem_func_ptr;
fptr func_ptr;

mem_func_ptr = &classname::add;
func_ptr = (fptr)(&classname::add);

This cast will cause undefined behavior.

[snip]
3. If this approach is not correct, then could you please advise as to how
to go about with it?

As John said, create a normal (non-member) function which calls your
member function. However, you need to remember that you must pass an
object (or reference or pointer to an object) of your class in order
to call the member function.
 
R

Rob Williscroft

Bob Hairgrove wrote in in
comp.lang.c++:
^^^
What is that? Is this legal C++?

Yes its from C:

struct X
{
int x;
} x;

Same as:

struct X
{
int x;
};

struct X x; // in C and C++ and
X x; // C++ only.

This is why a semicolon is required after class/struct/union defenitions.

Rob.
 
B

Bob Hairgrove

Bob Hairgrove wrote in in
comp.lang.c++:


Yes its from C:

struct X
{
int x;
} x;

No ... IF one uses this syntax in C++, it should be used like this:

typedef struct X
{
int x;
} x;

and not for classes.
Same as:

struct X
{
int x;
};

struct X x; // in C and C++ and
X x; // C++ only.

This is why a semicolon is required after class/struct/union defenitions.

Rob.

This syntax is not in the C++ standard ... although some compilers
might accept it, it is not standard C++ as far as I can tell.

Does that make it "legal"?
 
X

Xenos

Bob Hairgrove said:
No ... IF one uses this syntax in C++, it should be used like this:

typedef struct X
{
int x;
} x;
No, he was declaring an object of the classes, not a typedef. The sytax is
legal.
and not for classes.
Yes it is.
This syntax is not in the C++ standard ... although some compilers
might accept it, it is not standard C++ as far as I can tell.
Yes, it is standard and perfectly legal.
Does that make it "legal"?
moot point.
 
B

Bob Hairgrove

On Tue, 29 Jun 2004 15:05:01 -0400, "Xenos"

[snip]
Yes, it is standard and perfectly legal.
[snip]

Well, I'm always willing to learn something new ... can you quote me
chapter and verse where this is written in the standard? I looked all
over, but did not find it.

(BTW, which is the "real" class name afterwards, X or obj)?

Thanks.
 
X

Xenos

Bob Hairgrove said:
On Tue, 29 Jun 2004 15:05:01 -0400, "Xenos"

[snip]
Yes, it is standard and perfectly legal.
[snip]

Well, I'm always willing to learn something new ... can you quote me
chapter and verse where this is written in the standard? I looked all
over, but did not find it.
For which part, the way he created the object or the different ways he used
the class name?

Do I really need to dig out the standard??? I *really* believe that these
are not syntatically correct???

struct X {
int x;
} obj;

struct X obj2;
X obj3;

Or did *I* misunderstand what he wrote?
(BTW, which is the "real" class name afterwards, X or obj)?
X is the class name. obj is an object of the class.
 
X

Xenos

Xenos said:
Do I really need to dig out the standard??? I *really* believe that these
are not syntatically correct???

Sorry. Replace "I" in the second sentence to "Do you."
 
R

Rob Williscroft

Bob Hairgrove wrote in in
comp.lang.c++:
On Tue, 29 Jun 2004 15:05:01 -0400, "Xenos"

[snip]
Yes, it is standard and perfectly legal.
[snip]

Well, I'm always willing to learn something new ... can you quote me
chapter and verse where this is written in the standard? I looked all
over, but did not find it.

Its quite hard to find, you need to chase down all the gramma
defenition's, search for "class-specifier" and "type-specifier".

Possibly you might want to start with the gramma summery in
appendix A (A.6 declaration's and A.8 classes).

In essence ( substitute ... with something leagal :) :

class X { ... } /* no semicolon */

is a class-specifier, which is also a type-specifier,
which is also a decl-specifier, which is the first part of
a simple-declaration.

The second part of a simple-declaration is the declarator,
i.e the thing being declared.

class X { ... } obj;

This declares the type 'X' and an instance of type 'X' 'obj'.

However 7/2 gives permission to omit the declarator in this
case (as X is also being declared), so in fact it is:

class X { ... };

Which is the exception to the rule.
(BTW, which is the "real" class name afterwards, X or obj)?

obj is not a type name its an instance of type classname (from
the OP's post).

Rob.
 
B

Bob Hairgrove

On 29 Jun 2004 20:19:39 GMT, Rob Williscroft <[email protected]>
wrote:

[snip lots of patient explanation]
class X { ... } obj;

This declares the type 'X' and an instance of type 'X' 'obj'.

However 7/2 gives permission to omit the declarator in this
case (as X is also being declared), so in fact it is:

class X { ... };

Which is the exception to the rule.


obj is not a type name its an instance of type classname (from
the OP's post).

Thanks very much for your patience ... I totally screwed up here,
missing "obj" for the instance name!

That's what happens after you have been indoctrinated for 10+ years to
always separate the class declaration from the implementation.
 
B

Bob Hairgrove

Bob Hairgrove said:
On Tue, 29 Jun 2004 15:05:01 -0400, "Xenos"

[snip]
Yes, it is standard and perfectly legal.
[snip]

Well, I'm always willing to learn something new ... can you quote me
chapter and verse where this is written in the standard? I looked all
over, but did not find it.
For which part, the way he created the object or the different ways he used
the class name?
[snip]

I totally missed the fact that he was *creating an instance* of his
class immediately after the class declaration (see my post to Rob W.
for more...).

Sorry for the FUD.
 
P

PKH

Albert said:
Hi,

I need to pass a pointer-to-member-function as a parameter to a function
which takes pointer-to-function as an argument. Is there any way to do it
besides overloading the function?

Here is a small program I wrote to check if I could get the address of the
function from the member-function-pointer, so that I could pass it to the
function as a normal function-pointer.

---------------------------------------------------
#include<stdio.h>

class classname{
public:
int add(int a, int b){
printf("inside add. \ta = %d, b = %d\n", a,b);
return a+b;
}
}obj;


typedef int(classname::*mfptr)(int, int);
typedef int (*fptr)(int, int);


main(){

mfptr mem_func_ptr;
fptr func_ptr;

mem_func_ptr = &classname::add;
func_ptr = (fptr)(&classname::add);

printf("&classname::add is %llx\n", &classname::add);
printf("&classname::add is %llx\n", &classname::add);

printf("mem_func_ptr is %llx\n", mem_func_ptr);
printf("func_ptr is %x\n\n", func_ptr);

printf("add called with func_ptr. sum is %d\n\n", func_ptr(2,3));
printf("add called with mem_func_fptr. sum is %d\n\n",
(obj.*mem_func_ptr)(2,3));
}

-----------------------------------------------------


I compiled it with the -Wno-pmf-conversions option. Here is the output of
the program:

------------------------------------------
&classname::add is ffbeee78ff23e5d0
&classname::add is ffbeee78ff243a4c

mem_func_ptr is ffbeee78ff243a4c
func_ptr is 109bc

inside add. a = 3, b = 68028
add called with func_ptr. sum is 68031

inside add. a = 2, b = 3
add called with mem_func_fptr. sum is 5

------------------------------------------


A few questions:

1. Why is the value of '&classname::add' in the two lines different?

If the code you show is actually the one running, I find this very strange
since
as far as I can tell, the codelines for your 2 print-statements are
identical.
2. Why does the value of parameter 'b' change when 'classname::add' is
called with 'func_ptr'?

I believe all memberfunctions have a hidden 'this' parameter. When you're
calling
a memberfunction as a regular function, the 'this' parameter is not added to
the stack
and you will get undefined behaviour.
3. If this approach is not correct, then could you please advise as to how
to go about with it?

It's hard to make recommodations withouth knowing much about how it is going
to be used,
but I think I would stay with either just regular function-pointers or just
memberfunction-pointers.
You can do much fun stuff with memberfunction-pointers, like passing
different virtual memberfunctions
as parameters to other memberfunctions.

PKH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,174
Messages
2,570,941
Members
47,476
Latest member
blackwatermelon

Latest Threads

Top