Non-Subspace Related Coding - (c++) Pointer-to-member function stored in STL map
grazzhoppa - Thu Aug 07, 2008 12:32 am
Post subject: (c++) Pointer-to-member function stored in STL map
edit: I solved it, but would like an explanation.
What is the syntax for invoking a function stored as a value in STL map as a pointer-to-member function, through a map<>::iterator.
STL map Class member declaration
map<long, void (UserData::*)(CORE_DATA *cd)> *timersBot;
/* timersBot is a pointer to an STL map<>
* that has an integer as the key,
* and a pointer-to-a member function of UserData-class as the value
Class being used in code
map<long, void (UserData::*)(CORE_DATA *cd)>::iterator iter = /* assume the iterator is valid */
CORE_DATA *cd = /* assume this is valid */
/* What I've tried: */
(iter->*second)(cd); // compiler error " 'second' was not declared in this scope"
(*(iter->second))(cd); // compiler error " invalid use of `unary *' on pointer to member"
UserData *ud = /* assume this is valid */
ud->*(iterBotT->second)(cd); // compiler error " must use .* or ->* to call pointer-to-member function .....
* How can invoke the function from the pointer-to-function
* that's stored in iter->second ?
(ud->*iterBotT->second)(cd); // IT COMPILES but why?
Snrrrub - Fri Aug 08, 2008 12:25 pm
Every invocation of a member function is associated with an object. Consider:
In this case, SendMessage is invoked on the object 'p'. In the implementation of Player::SendMessage, you can refer to the object 'p' through the pointer 'this'. It's useful to imagine that every invocation of a member function in C++ involves a hidden 'this' argument.
Function pointers to member functions are no different. You still have to specify *which* object you're invoking the method on. That's why your first two attempts didn't succeed. When you store a function pointer, you're ONLY storing the function pointer, not the <object, function pointer> pair that you need to make a successful call.
The code above fails because of operator precedence: in this case, the function call has higher precedence than the member dereference operation so it thinks you're attempting to take the return value of the function call and dereference that in the object 'ud'.
The example that compiles works because you've:
1) specified the object on which to call the member function ('ud')
2) you've dereferenced the member function correctly
3) applied the function call AFTER dereferencing the member function (the parentheses around ud->*iterBotT->second)
Note that -> has a higher precedence than * so when you say *iterBotT->second, it really means *(iterBotT->second) so you get the expected results.
This is a good site to learn more about function pointers: http://www.newty.de/fpt/index.html
A good C++ operator precedence and associativity table is here: http://cs.smu.ca/~porter/csc/ref/cpp_operators.html
Anonymous - Sat Aug 09, 2008 12:46 am
Thank you, I understand it now. You were very clear
It helps me to think that pointers-to-member functions are more like an offset rather than an actual memory address.
Would be like saying "execute the member function of this particular Class object. The member function has the memory address equal to Class's base address plus the offset specified by the "pointer-to-member_function." I'm not sure if this is what's happening in reality, but it helps me to think of it that way.
If pointer-to-member functions were actual memory addresses, then there would be a common mistake of trying to execute a member function of a object that had been destroyed since storing the function pointer.
Anonymous - Thu Jul 30, 2009 3:11 pm
Post subject: Broader question
That is a very detailed explanation.
I have a follow up question.
What could be reason's that the object reference of a FP
is not defaulted to the current object scope,
why an explicit use of *this* is needed.
Bak - Thu Jul 30, 2009 6:18 pm
my guess is that a function pointer is just an address, and the address of the function is shared for all instances of the class (which secretly pass in a base pointer to the data for the instance of the class when you call it). It may be possible the user intended to call the function on a different instance of the class, so you must be explicit.
john310 - Tue Apr 26, 2011 6:05 am
In fact, the STL's map class allows you to store data by any type of key instead of simply by a numerical key, the way you must access an array or vector. So instead of having to compute a hash function and then access an array, you can just let the map class do it for you.
To use the map class, you will need to include <map> and maps are part of the std namespace. Maps require two, and possibly three, types for the template:
std::map <key_type, data_type, [comparison_function]>
Notice that the comparison function is in brackets, indicating that it is optional so long as your key_type has the less-than operator, <, defined -- so you don't need to specify a comparison function for so-called primitive types such as int, char, or even for the string class. Moreover, if you overloaded the < operator for your own class, this won't be necessary.
The reason that the key type needs the less-than operator is that the keys will be stored in sorted order -- this means that if you want to retrieve every key, value pair stored in the map, you can retrieve them in the order of the keys.
Let's go back to the example of storing student grades. Here's how you could declare a variable called grade_list that associates strings (student names) with characters (grades -- no + or - allowed!).
std::map <string, char> grade_list;
Samapico - Tue Apr 26, 2011 10:22 pm
Good job, bot and/or retarded exploited child, you can copy paste a webpage:
Give him hell, MGB!