11

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

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++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ' &Foo::func ' [-fpermissive]
void (Foo::*getPointer())(int) { return &func; }

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

+0

@JoachimPileborg Область видимо. Если есть переменная, отличная от члена с тем же именем, что и переменная класса, мне не нужно указывать класс. –

+1

А я неправильно понял ваш вопрос, вы спрашиваете о необходимости «Foo ::' в '& Foo :: func'. –

+1

@JoachimPileborg Да, это заставляет меня болтать, почему компилятор не может понять это. Мне не нужно указывать статические функции, переменные-члены, когда я вызываю функции или даже беру адрес переменной-члена; но по какой-то причине, если я хочу указать адрес функции, которую я должен указать. –

ответ

3

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

Static class members are objects or functions, and pointers to them are ordinary pointers to objects or functions

Эта проблема с этим, я думаю, хорошо описано в this quote in an answer from Johannes из Annotated C++ Reference Manual(ARM):

Note that the address-of operator must be explicitly used to get a pointer to member; there is no implicit conversion ... Had there been, we would have an ambiguity in the context of a member function ... For example,

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

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

+0

Думаю, мне нужно подобрать копию ARM, чтобы перейти к моему D & E, вы не можете купить pdf-файл :-( –

+0

Думаю, я получил его, глядя на ваш ответ в сочетании с [ dyp's comment] (http: // stackoverflow.ком/вопросы/32842429/почему-делает взятие-а-член-функция-указатель стоимости требует класса имя-qualificatio/32845696 # comment53523542_32842429). Когда я делаю '& B ::', я получаю смещение не по абсолютному адресу. Наверное, я должен понимать, что все методы вызываются смещением, * не * фактическим адресом? –

+1

@JonathanMee, это одна возможная реализация, чтение [Указатели на функции членов - очень странные животные] (http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspx) должны быть полезны , –

3

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

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

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 является вызов func в классе Foo при вызове &Foo::func - это виртуальный вызов.

+0

Большое вам спасибо. Все это имеет смысл сейчас. –

+2

Это неправильно. Нестатический адрес функции-члена не является указателем и требует использования 'this', поэтому ему не нужно разрешать« адрес »во время компиляции. Более того, если 'mp' указывает на' Foo :: func', и вы вызываете его на экземпляр 'Bar', то будет вызываться версия' Bar :: func'. – 6502

+0

@ 6502 Arg! Вы снимаете единственное разумное объяснение, которое я слышал! –