指向成员的访问运算符:.* 和 ->*
指向成员的访问运算符.* 和->* 用于解除对指向成员的指针 与对象 和 的组合>分别指向对象的指针。此描述适用于指向数据成员的指针和指向成员函数的指针。
例如,考虑类Foo:
struct Foo {
int i;
void f();
};
如果您将成员指针iPtr 声明为指向Foo 的int 数据成员:
int Foo::* iPtr;
你可以初始化这个成员指针iPtr,让它指向Foo::i成员:
iPtr = &Foo::i;
要取消引用此指针,您需要将它与Foo 对象结合使用。
现在考虑对象foo 和指向对象fooPtr 的指针:
Foo foo;
Foo* fooPtr = &foo;
然后,您可以取消引用 iPtr 与 foo 或 fooPtr 的组合:
foo.*iPtr = 0;
fooPtr->*iPtr = 0;
类似地,您可以将.* 和->* 与指向函数成员的指针一起使用。但是请注意,您需要将它们括在括号之间,因为 函数调用运算符,即(),比.* 和->* 具有更高的优先级:
void (Foo::*memFuncPtr)() = &Foo::f;
(foo.*memFuncPtr)();
(fooPtr->*memFuncPtr)();
总结:您需要一个对象来取消引用指向成员的指针,而您使用哪个对象,.* 或->* 来取消引用指向成员的指针,取决于该所需对象是直接提供还是通过一个对象指针。
C++17 — 改用std::invoke()
从 C++17 开始,std::invoke 函数模板可以替换这两个运算符的使用。 std::invoke 提供了一种统一的方式来取消引用成员指针,无论您是否将它们与 object 或 object pointer 结合使用,也无论 指向成员的指针对应于一个指向数据成员的指针或指向成员函数的指针:
// 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
这种统一的语法对应于普通的函数调用语法,可能更容易编写泛型代码。