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

19

我在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 函数本来就是一个地址,不是吗?


6
一个是C++,另一个不是。 - Kerrek SB
有点不方便,但那只是必需的语法。 - Neil Kirk
& 运算符返回 something 的地址。在这种情况下,它返回函数的地址,以便可以在运行时调用它。 - Giovanni Botta
1
OP在(隐含地)指出函数符号和数组符号一样,x&x的值必须相同。也许编译器在处理函数时不喜欢没有&的语法(尽管根据编译错误,这似乎与函数重载有关)。无论如何,在我看来,这是一个非常好的问题。 - barak manos
3个回答

15
这是函数指针转换的确切定义,[conv.func]:
引用类型为T的函数lvalue可以转换为类型为“指向T的指针”的prvalue。结果是函数的指针。55 注释55):非静态成员函数不适用于此转换,因为无法获取引用非静态成员函数的lvalue。
因此,我们看到普通的非成员函数中出现的衰减不适用于此情况,您需要显式地获取地址。
即。
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 或者是静态成员函数。


3
唯一解释其推理背后原因的答案。 - tux3
为什么这是个好主意是另一个问题。第一个原因是为了与C兼容。但是,天下间为什么标准要区分第二种和第三种情况(是否存在“static”)? - abligh
1
假设A::f被隐式转换为指向成员函数的指针。那么对于struct B:A {void f(){auto x = A :: f; x(); }},甚至是struct B:A {void f(){A :: f(); }}会发生什么(后者目前是完全有效的C ++)?非静态成员函数和静态成员函数的处理方式有所不同,因为这是必要的,因为非静态成员函数与非成员函数和静态成员函数有很大的不同,因此将其视为相同实际上是不可能的。 - user743382

6
对于全局(非成员)函数,函数名称求值为该函数的地址,除非将其传递给 & 运算符,在这种情况下,函数名称就不再是地址。因此,您可以直接或使用 & 来分配一个指向函数的指针,例如:
int f() {}

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

因此,在这种情况下,这两者之间实际上没有区别。
但是对于成员函数,规则略有不同。在这种情况下,必须使用符号“&”,如果省略符号“&”,则编译器将无法编译代码(假设编译器正常运行)。
这并没有特别的原因 - 这只是Bjarne决定事物应该如何进行的方式。如果他决定希望成员函数的名称求值为指向成员的指针(与非成员函数的工作方式相同),那么他可以这样做。
除静态成员函数外,其他成员函数大多类似于非成员函数。

1
“这没有特别的原因”可能是答案的关键点。我想OP之前一直在自问这个问题。 - barak manos

2
当一个函数是类的非静态成员函数时,在表达式中期望指向该成员函数的指针时,需要使用形式&ClassName::functionName
当一个函数是类的静态成员函数时,当在表达式中期望指向该函数的指针时,可以使用ClassName::functionName&ClassName::functionName两种形式。
当一个函数是全局函数时,即非成员函数时,在表达式中期望指向该函数的指针时,可以使用functionName&functionName两种形式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接