В чем разница между &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 19

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