Подтвердить что ты не робот

Почему для принятия значения указателя функции члена требуется классное определение класса даже изнутри класса?

При возврате указателя функции-члена в класс внутри одной из этих функций-членов класса мне все равно нужно указать класс. Я не могу просто взять адрес. Например, этот код отлично работает:

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

Но если в getPointer я пытаюсь просто сделать: return &func Я получаю эту ошибку:

prog.cpp: В функции-члена 'void (Foo::* Foo::getPointer())(int)':
prog.cpp: 8: 43: error: ISO С++ запрещает принимать адрес неквалифицированной или нестационарной функции-члена в виде скобки, чтобы сформировать указатель на функцию-член. Скажите '&Foo::func' [-fpermissive]
  void (Foo::*getPointer())(int) { return &func; }

Почему я должен указывать класс, когда тот контекст, в котором я находится?

4b9b3361

Ответ 1

Указатели и указатели на элементы - это разные типы, мы можем видеть, что из раздела проект стандартного раздела С++ 3.9.2 [basic.compound], который включает составной тип для указателя, а также указатель на нестатический член класса и примечания

Статические члены класса - это объекты или функции, а указатели на них обычные указатели на объекты или функции

Эта проблема с этим, я думаю, хорошо описана в этой цитате в ответе от Johannes из Аннотированное справочное руководство по С++ (ARM):

Обратите внимание, что адрес-оператор должен быть явно использован для получения указатель на член; нет никакого неявного преобразования... Если бы было, мы будем иметь двусмысленность в контексте функции-члена... Для Например,

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*'

продемонстрируйте разницу между квалифицированным и неквалифицированным именем.

Ответ 2

(... был неправильный ответ...)

Это выглядит более странно в следующем контексте:

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;
}

Выходной сигнал

Привет мир
4

Вызов Foo::func - это вызов func в классе Foo, а вызов &Foo::func - это виртуальный вызов.