&foo::function 和 foo::function 有什么区别?

What is the difference between &foo::function and foo::function?

我正在 linux 上使用 gtkmm 库为我的 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 函数不就是一个地址吗?

这是函数到指针转换的确切定义,[conv.func]:

An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.55


55) This conversion never applies to non-static member functions because an lvalue that refers to a non-static member function cannot be obtained.

因此,我们在普通非成员函数中看到的衰减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,但是,规则有点不同。在这种情况下, & 是必需的;如果您试图省略 &,则代码根本无法编译(假设编译器正常运行)。

没有什么特别的理由一定会是这种情况——这就是 Bjarne 决定事情应该如此的方式。如果他决定他想要一个成员函数的名称来评估一个指向成员的指针(相当于非成员函数的工作方式),他就可以做到这一点。


1.除了静态成员函数,它们大多像非成员函数一样。

当函数是 class 的非静态成员函数时,当表达式中需要指向成员函数的指针时,有必要使用 &ClassName::functionName 形式。

当函数是 class 的静态成员函数时,当表达式中需要指向函数的指针时,ClassName::functionName&ClassName;:functionName 都可以使用。

当函数是全局函数,即非成员函数时,当表达式中需要指向函数的指针时,functionName&functionName 都可以使用。