#include <iostream>
class Person
{
public:
Person();
~Person();
int GetAge() {return age;}
staticint GetPopulation() {return population;}
private:
int age;
staticint 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):
Errors are:
Invalid use of non-static member function 'void myClass::ShowMember()'
Cannot convert 'void(myClass::)()' to 'void (myClass::*)()' in assignment
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.
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: