Pointer-to-member access operators: .*
and ->*
The pointer-to-member access operators, .*
and ->*
, are for dereferencing a pointer to member in combination with an object and a pointer to object, respectively. This description applies to both pointers to data members and pointers to member functions.
For example, consider the class Foo
:
struct Foo {
int i;
void f();
};
If you declare a member pointer, iPtr
, to an int
data member of Foo
:
int Foo::* iPtr;
You can initialize this member pointer iPtr
so that it points to the Foo::i
member:
iPtr = &Foo::i;
To dereference this pointer, you need to use it in conjunction with a Foo
object.
Consider now the object foo
and the pointer to object fooPtr
:
Foo foo;
Foo* fooPtr = &foo;
Then, you can dereference iPtr
in combination with foo
or fooPtr
:
foo.*iPtr = 0;
fooPtr->*iPtr = 0;
Analogously, you can use .*
and ->*
with pointers to function members. Note however that you will need to enclose them between parentheses because the function call operator, i.e., ()
, has higher precedence than both .*
and ->*
:
void (Foo::*memFuncPtr)() = &Foo::f;
(foo.*memFuncPtr)();
(fooPtr->*memFuncPtr)();
To conclude: you need an object to dereference a pointer to a member, and which one you use, either .*
or ->*
for dereferencing the pointer to member, depends on whether this needed object is directly provided or through an object pointer.
C++17 — Using std::invoke()
instead
The use of both operators can be replaced since C++17 by the std::invoke
function template. std::invoke
provides a unified way of dereferencing member pointers regardless of whether you use them in combination with an object or an object pointer, and also regardless of whether the pointer to member corresponds to a pointer to data member or pointer to member function:
// dereference a pointer to a data member
std::invoke(iPtr, foo) = 0; // with an object
std::invoke(iPtr, fooPtr) = 0; // with an object pointer
// dereference a pointer to a member function
std::invoke(memFuncPtr, foo); // with an object
std::invoke(memFuncPtr, fooPtr); // with an object pointer
This unified syntax corresponds to the ordinary function call syntax, and it may make it easier to write generic code.