|
Written by Hemanshu Patel
|
|
Monday, 22 October 2007 |
|
Page 4 of 9 Operator->*
The operator–>* is a binary operator that behaves like all the other binary operators. It is provided for those situations when you want to mimic the behavior provided by the built-in pointer-to-member syntax, described in the previous chapter. Just like operator->, the pointer-to-member dereference operator is generally used with some kind of object that represents a “smart pointer,” although the example shown here will be simpler so it’s understandable. The trick when defining operator->* is that it must return an object for which the operator( ) can be called with the arguments for the member function you’re calling. The function call operator( ) must be a member function, and it is unique in that it allows any number of arguments. It makes your object look like it’s actually a function. Although you could define several overloaded operator( ) functions with different arguments, it’s often used for types that only have a single operation, or at least an especially prominent one. You’ll see in Volume 2 that the Standard C++ Library uses the function call operator in order to create “function objects.” To create an operator->* you must first create a class with an operator( ) that is the type of object that operator->* will return. This class must somehow capture the necessary information so that when the operator( ) is called (which happens automatically), the pointer-to-member will be dereferenced for the object. In the following example, the FunctionObject constructor captures and stores both the pointer to the object and the pointer to the member function, and then the operator( ) uses those to make the actual pointer-to-member call: //: C12:PointerToMemberOperator.cpp #include <iostream> using namespace std;
class Dog { public: int run(int i) const { cout << "run\n"; return i; } int eat(int i) const { cout << "eat\n"; return i; } int sleep(int i) const { cout << "ZZZ\n"; return i; } typedef int (Dog::*PMF)(int) const; // operator->* must return an object // that has an operator(): class FunctionObject { Dog* ptr; PMF pmem; public: // Save the object pointer and member pointer FunctionObject(Dog* wp, PMF pmf) : ptr(wp), pmem(pmf) { cout << "FunctionObject constructor\n"; } // Make the call using the object pointer // and member pointer int operator()(int i) const { cout << "FunctionObject::operator()\n"; return (ptr->*pmem)(i); // Make the call } }; FunctionObject operator->*(PMF pmf) { cout << "operator->*" << endl; return FunctionObject(this, pmf); } }; int main() { Dog w; Dog::PMF pmf = &Dog::run; cout << (w->*pmf)(1) << endl; pmf = &Dog::sleep; cout << (w->*pmf)(2) << endl; pmf = &Dog::eat; cout << (w->*pmf)(3) << endl; } ///:~ Dog has three member functions, all of which take an int argument and return an int. PMF is a typedef to simplify defining a pointer-to-member to Dog’s member functions. A FunctionObject is created and returned by operator->*. Notice that operator->* knows both the object that the pointer-to-member is being called for (this) and the pointer-to-member, and it passes those to the FunctionObject constructor that stores the values. When operator->* is called, the compiler immediately turns around and calls operator( ) for the return value of operator->*, passing in the arguments that were given to operator->*. The FunctionObject::operator( ) takes the arguments and then dereferences the “real” pointer-to-member using its stored object pointer and pointer-to-member. Notice that what you are doing here, just as with operator->, is inserting yourself in the middle of the call to operator->*. This allows you to perform some extra operations if you need to. The operator->* mechanism implemented here only works for member functions that take an int argument and return an int. This is limiting, but if you try to create overloaded mechanisms for each different possibility, it seems like a prohibitive task. Fortunately, C++’s template mechanism (described in the last chapter of this book, and in Volume 2) is designed to handle just such a problem.
|