В чем разница между &foo::function и foo::function?
Я использую библиотеку gtkmm в linux, чтобы нарисовать простое меню для моего GUI.
В приведенном ниже коде компилятор жаловался на невозможность разрешить адрес
sigc::mem_fun(*this, AppWindow::hide)));
^
appwindow.cpp:15:41: note: could not resolve address from overloaded function
Но когда я вставляю &
, он компилируется отлично
m_menu_app.items().push_back(MenuElem("Quit",
sigc::mem_fun(*this, &AppWindow::hide)));
Какая здесь разница? Разве функция hide
не является просто адресом в первую очередь?
3 ответа:
Это точное определение преобразования функции в указатель, [conv.func]:
Значение lvalue типа функции
T
может быть преобразовано в prvalue типа "указатель наT
."Результатом является указатель на функцию.55
55)это преобразование никогда не применяется к нестатическим функциям-членам, поскольку значение lvalue, которое ссылается на нестатическую функцию-член невозможно получить .
Таким образом, распад, который мы смотрите с обычными функциями, не являющимися членами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 или статические функции-члены.
Для глобальных (не являющихся членами) функций имя функции вычисляется по адресу этой функции, за исключением тех случаев, когда оно передается оператору
&
, поэтому вы можете (например) назначить указатель на функцию либо с&
, либо без него эквивалентно:Таким образом, в данном случае нет никакой разницы между ними.int f() {} int (*pf1)() = f; int (*pf2)() = &f;
Для функций членов 1, однако правила немного отличаются. В этом случае требуется
Нет никакой особой причины, по которой это должно было бы быть так-просто так решил Бьярне. Если бы он решил, что ему нужно имя функции-члена, чтобы вычислить указатель на член (эквивалентно тому, как все работает для функций, не являющихся членами), он мог бы это сделать.&
; Если вы попытаетесь опустить&
, код просто не будет компилироваться (предполагая, что правильно функционирующий компилятор, в любом случае).
1. Кроме статических функций-членов, которые в основном действуют как не-члены функции.
Если функция является нестатической функцией-членом класса, то необходимо использовать форму
&ClassName::functionName
, когда в выражении ожидается указатель на функцию-член.Когда функция является статической функцией-членом класса, можно использовать как
ClassName::functionName
, так и&ClassName;:functionName
, когда в выражении ожидается указатель на функцию.Если функция является глобальной, то есть не является членом, то можно использовать как
functionName
, так и&functionName
, когда указатель на функцию ожидается в выражение.