В чем разница между & 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
только адресом в первую очередь?
Ответы
Ответ 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
могут использоваться, когда в выражении ожидается указатель на функцию.