为什么接受成员函数指针值即使在类内部也需要类名限定?

Why does taking a member function pointer value requires class name qualification even from inside of the class?

本文关键字:内部 成员 函数 指针 为什么      更新时间:2023-10-16

当返回一个成员函数指针到一个类的成员函数中时,我仍然必须指定这个类。我不能简单地记下地址。例如,下面的代码工作得很好:

class Foo {
public:
    void func(int param) { cout << param << endl; }
    void (Foo::*getPointer())(int) { return &Foo::func; }
};

但是如果在getPointer我尝试简单地做:return &func我得到这个错误:

prog.cpp: In member function ' void (Foo::* Foo::getPointer())(int) ':
prog.cpp:8:43: error: ISO c++禁止接受非限定或带括号的非静态成员函数的地址来形成指向成员函数的指针。说' &Foo::func ' [-fpermissive]
void (Foo::*getPointer())(int) { return &func; }

为什么我必须指定类,当那是我所在的上下文?

指针和指向成员的指针是不同的类型,我们可以从c++标准草案部分3.9.2 [basic.compound]中看到,它包括指针的复合类型以及指向非静态类成员的指针和注释:

静态类成员是对象或函数,以及指向它们的指针是指向对象或函数的普通指针

我认为这个问题在注释c++参考手册(ARM)中Johannes的回答中有很好的描述:

注意,必须显式地使用寻址操作符来获取a成员指针;没有隐式转换……如果有的话,在成员函数的上下文中,我们会有歧义…为例如,

void B::f() {
    int B::* p = &B::i;   // ok
    p = B::i;         // error: B::i is an int
    p = &i;           // error: '&i'means '&this->i'
                      // which is an 'int*'
    int *q = &i;      // ok
    q = B::i;         // error: 'B::i is an int
    q = &B::i;        // error: '&B::i' is an 'int B::*'
}

特别是这几行:

int B::* p = &B::i; // OK

:

p = &i; // error: '&i'means '&this->i' which is an 'int*'

说明限定名和非限定名的区别

(…有一个错误的答案…)

在以下上下文中看起来更奇怪:

class Foo {
public:
    virtual void func(int param) { cout << param << endl; }
    void call(int x) { Foo::func(x); }
    void (Foo::*getPointer())(int) { return &Foo::func; }
};
class Bar : public Foo {
public:
    void func(int param) override { cout << "Hello world!" << endl; }
};

int main() {
    Foo *a = new Bar();
    auto p = a->getPointer();
    (a->*p)(4);
    a->call(4);
    return 0;
}

输出为

Hello world
4

调用Foo::func是对Foo类中的func的调用,而调用&Foo::func是虚调用。