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

В чем разница между & foo:: function и foo:: function?

Я использую библиотеку gtkmm в linux для рисования простого меню для моего графического интерфейса.

В приведенном ниже коде компилятор жаловался на неспособность разрешить адрес

        sigc::mem_fun(*this, AppWindow::hide)));
                                         ^
appwindow.cpp:15:41: note:   could not resolve address from overloaded function

Но когда я вставляю &, он компилирует fine

m_menu_app.items().push_back(MenuElem("Quit",
    sigc::mem_fun(*this, &AppWindow::hide)));

Какая разница здесь? Не является ли функция hide только адресом в первую очередь?

4b9b3361

Ответ 1

Это точное определение преобразования функции в указатель, [conv.func]:

Значение типа функции T может быть преобразовано в prvalue типа "указатель на T." Результатом является указатель на функцию. 55


55) Это преобразование никогда не применяется к нестационарным функциям-членам, поскольку значение l, которое относится к нестатической функции-члену не может быть получено.

Таким образом, распад, который мы видим с нормальными, нечленными функциями 1 не применяется, и вам нужно явно принять адрес.

т.е.

void f();

struct A {
    void f();
    static void g();
};


auto a = f; // Ok: auto deduced as void(*)()
auto b = A::f; // Error: A::f not an lvalue, auto cannot be deduced
auto c = A::g; // Ok: auto deduced as void(*)()


1 или статические функции-члены.

Ответ 2

Для глобальных (нечленовских) функций имя функции оценивается по адресу этой функции, кроме случаев, когда она передается оператору &, поэтому вы можете (например) назначить указатель на функцию либо с помощью или без & эквивалентно:

int f() {}

int (*pf1)() = f;
int (*pf2)() = &f;

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

Для функций-членов 1 однако, правила немного отличаются. В этом случае требуется &; если вы попытаетесь опустить &, код просто не будет компилироваться (при условии, что он правильно работает в компиляторе).

Нет особых причин, по которым это должно было быть так - это именно то, как Бьярне решил, что все должно быть. Если бы он решил, что ему нужно, чтобы имя функции-члена оценивалось указателем на член (что эквивалентно тому, как все работает для функций, не являющихся членами), он мог бы это сделать.


1. Помимо статических функций-членов, которые в основном действуют как функции, не являющиеся членами.

Ответ 3

Когда функция является нестатической функцией-членом класса, тогда необходимо использовать форму &ClassName::functionName, когда в выражении ожидается указатель на функцию-член.

Если функция является статической функцией-членом класса, то как ClassName::functionName, так и &ClassName;:functionName могут использоваться, когда в выражении ожидается указатель на функцию.

Когда функция является глобальной, то есть функцией, не являющейся членом, обе functionName и &functionName могут использоваться, когда в выражении ожидается указатель на функцию.