Pointer to Member Function Giving Errors

I've been working out of Sam's Teach Yourself C++ in 21 Days.
One of the exercises in the book involved the following code that I wrote:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

class Person
{
public:
	Person();
	~Person();
	int GetAge() {return age;}
	static int GetPopulation() {return population;}
private:
	int age;
	static int population;
};

Person::Person():
age(1)
{
	population++;
}

Person::~Person()
{
	std::cout << "Population is " << population << ".\n";
	population--;
	std::cout << "Population is now " << population << ".\n\n";
}

int Person::population = 0;

int main()
{
	int (Person::*PMF) ();
	PMF = Person::GetAge;
	
	Person Tom, Dick, Harry;
	std::cout << "Tom is " << (Tom.*PMF)() << " years old.\nThe Populations is " << Person::GetPopulation() << ".\n\n";
	std::cout << "Dick is " << (Dick.*PMF)() << " years old.\nThe Populations is " << Person::GetPopulation() << ".\n\n";
	std::cout << "Harry is " << (Harry.*PMF)() << " years old.\nThe Populations is " << Person::GetPopulation() << ".\n\n";
	 
return 0;
}


However, this line:
 
PMF = Person::GetAge;

gives 2 errors:
Invalid use of non-static member function 'int Person::GetAge()'
Cannot convert 'int(Person::)()' to 'int (Person::*)()' in assignment


This was code I made for the exercises at the end of chapter 15, but if I compile the example answer in the back of the book, i get very similar errors(only difference was example code used functions returning void instead of int, and implemented those functions slightly differently):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream.h>

     class myClass
     {
	     public:
	        myClass();
	        ~myClass();
	        void ShowMember();
	       static int GetStatic();
	    private:
	       int itsMember;
	       static int itsStatic;
    };

    myClass::myClass():
     itsMember(1)
   {
	       itsStatic++;
    }

    myClass::~myClass()
    {
	       itsStatic--;
	       cout << "In destructor. ItsStatic: " << itsStatic << endl;
	    }
	
	    void myClass::ShowMember()
		{
		       cout << "itsMember: " << itsMember << endl;
	    }
	
	    int myClass::itsStatic = 0;
	
	    int myClass::GetStatic()
	    {
		       return itsStatic;
	    }
	
	    int main()
	   {
		       void (myClass::*PMF) ();
		
		       PMF=myClass::ShowMember;
		
		       myClass obj1;
		       (obj1.*PMF)();
		       cout << "Static: " << myClass::GetStatic() << endl;
		
		       myClass obj2;
		       (obj2.*PMF)();
		       cout << "Static: " << myClass::GetStatic() << endl;
		
		       myClass obj3;
		      (obj3.*PMF)();
		       cout << "Static: " << myClass::GetStatic() << endl;
		     return 0;
	   }


Errors are:
Invalid use of non-static member function 'void myClass::ShowMember()'
Cannot convert 'void(myClass::)()' to 'void (myClass::*)()' in assignment


So, what's going on?
Try PMF = &myClass::ShowMember

(note ampersand).

Ok, that worked perfectly. Thanks!
Can you explain why exactly that worked, though? I'm confused
Not off the top of my head, but I can ask a colleague on Monday and post a reply then unless someone else beats me to it.

I just know that the ampersand is required to make a pointer to a member function. It doesn't seem like it should be necessary though.


Whoa, what do you want to do here? Seems like you want to use a pointer to a member function. Why? This is inherently dangerous, because at the pointer side you don't have the object, and without the object the function (if not static) is meaningless. And for C backward compatibility, using static functions, while it will work with most compilers, doesn't suffice either: you have to use C linkage, too. So again, what is the motivation? I'm sure there is a better solution for the problem (and there are better books than "XY in 21 Days"... if you want a good introductory book, get "The C++ Primer" by Lippman et al).

To answer your question why this works: just like the array-to-pointer decay there is a function-to-pointer decay (inherited from C), but it doesn't include member-function-to-pointer decay. You have to take their address explicitly (so your question really should have been: why does it work "sometimes" without the '&'?, since this is the actual exception).
Pointer to member functions are extremely useful in C++. They are C++'s way of providing a callback mechanism that would otherwise be done with static (ie, non-member) functions in C.

In fact, they are so useful that Boost has the function and bind libraries that simplify their use.

[Having said all this, I have not looked at what OP wanted to do and whether or not it makes sense to use pointer to members to accomplish it.]

I agree that there are a number of uses for such pointers and I am currently trying to take advantage of them to create a wrapper class with a static method that can be used to start threads from member functions of an object.

The wrapper class has just one static method that takes a pointer to an object that is generic and will be used to pass information as to what class::method to start.

I am however, having difficulty getting the syntax correct for access to the member function pointer from within the wrapper class, even though I am using the exact same syntax that compiles without errors when used from within the target methods class.

Given the following typedef:

typedef int (memOPS::*memFun)();

And this declaration:

memFun myFunc;

From within the class constructor I have this code that compiles without error:

myFunc = &this->myTargetFunction;
int i = (this->*myFunc )();

This compiles without errors and works as expected. However the following code used within my static method of the wrapper class does not compile correctly:

int i = (((memOPS *)ops)->*myFunc )();

In this code "ops" is a VOID * pointer to the object of interest. I know that VS is able to work with the cast since it will expand my possible choice of methods for me when I type the "->" and allow me to pick "myFunc from the list.

The error I am getting is C2065 : undeclared identifier

This is telling me that I do not have a properly defined prototype for the function that I am trying to call (at least that is what I believe), but I have not been able to dig out the correct syntax to get this past the compiler (VS2008).

By the way, I have this code in a ".h" file and the prototype for the memOPS class is included.

Any insight would be greatly appreciated...

Cheers,

creo

Last edited on
In doing some additional research and some testing, I managed to get the following to work from inside my wrapper class:

First I define this:

int (memOPS::*f)();

Then I initialize it as follows:

f = ((memOPS *)ops)->myFunc ;

And finally I call my function:

iret = (((memOPS *)ops)->*f)();

Clearly, if this extra step makes it work, one would think that with the proper syntax you should be able to just use the original value in the myFunc member without having to define "f" and reference the function through it .

At any rate, if someone has some insight on what I am missing here it would be greatly appreciated. As it is, this will be a workable solution although not as clean as I would like.

Cheers,

creo

UPDATE:

OK, well after further review and on giving some thought to what was going on here, I came up with the following syntax that compiles and yields the desired effect, although it is not a pretty sight:

iret = (((memOPS *)ops)->*(((memOPS *)ops)->myFunc ))();

Ah, isn't that just some grand syntax????

Cheers,

creo
Last edited on
Topic archived. No new replies allowed.