为什么可以按类类型获取成员函数的地址

Jac*_*hin 0 c++ bind member-function-pointers pointer-to-member

我遇到了这段代码:

 auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
Run Code Online (Sandbox Code Playgroud)

在前面的代码中,我们可以将地址运算符应用于成员函数,而没有创建实例对象,这怎么可能?

Ker*_* SB 5

C++的类型系统包含一些鲜为人知的类型,它们是指向成员的指针.给定任何类类型C和任何对象或函数类型T,都有一个指向成员的指针类型T C::*.可以通过将address-of运算符应用于类成员的限定名称来获取这些类型的值.例如:

 struct Foo;

 int Foo::* pi;                  // C = Foo, T = int
 void (Foo::* pf)(bool, int);    // C = Foo, T = void(bool, int)

 struct Foo {
     int a;
     int b;
     void f(bool, int);
     void g(bool, int);
 };

 pi = &Foo::a;
 pf = &Foo::f;
Run Code Online (Sandbox Code Playgroud)

成员指针本身只抽象地选择一个类成员,与任何类实例无关.要实际使用指针,您需要一个类实例和member-dereference运算符.*:

Foo x;

int n = x.*pi;     // gets x.a
(x.*pf)(true, n);  // calls x.f(true, n)

pf = &Foo::g;
(x.*pf)(true, n);  // calls x.g(true, n)
Run Code Online (Sandbox Code Playgroud)

(通过指向成员的指针调用表达式中的括号pf是必要的,否则表达式a.*b(c)意味着a.*(b(c)).这有时会让新用户感到困惑.)

不要将指向成员的指针与指向实际对象的指针混淆为对象成员!

int * p = &(x.*pi);   // p = &x.a
Run Code Online (Sandbox Code Playgroud)

这里p指向实际的int子对象x.a,它是一个普通的对象指针,而是pi一个指向成员的指针,它抽象地选择Foo::a一个Foo对象的成员.