【问题标题】:What is the difference between &foo::function and foo::function?&foo::function 和 foo::function 有什么区别?
【发布时间】:2015-03-08 07:42:46
【问题描述】:

我正在使用 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 函数一开始不就是一个地址吗?

【问题讨论】:

  • 一个是C++,另一个不是。
  • 有点不方便,但这只是必需的语法。
  • & 运算符返回 something 的地址。在这种情况下,它返回函数的地址,以便可以在运行时调用。
  • OP 在(隐含提及的)事实中是正确的,即对于函数符号,与数组符号一样,x&x 的值必须相同。当涉及到函数时,编译器可能不“喜欢”没有& 的语法(尽管根据编译错误,它与函数重载的事实特别有关)。无论如何,我认为这是一个非常好的问题。

标签: c++ function-pointers


【解决方案1】:

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

函数类型T的左值可以转换为类型的prvalue “指向T的指针。”结果是一个指向函数的指针。55


55)这种转换永远不会应用于非静态成员函数,因为左值引用了非静态成员函数 无法获得

因此,我们在正常的非成员函数中看到的衰减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 或静态成员函数。

【讨论】:

  • 解释其背后原因的唯一答案。
  • 为什么这是一个好主意是另一个问题。第一个是为了与 C 兼容。但是为什么标准要区分第二种和第三种情况(static 的存在)?
  • @abligh 假设 A::f 确实被隐式转换为指向成员函数的指针。那么struct B : A { void f() { auto x = A::f; x(); } },甚至struct B : A { void f() { A::f(); } }(后者目前是完全有效的C++)会发生什么?非静态成员函数和静态成员函数的处理方式之间存在差异,因为这是必要的,因为非静态成员函数与非成员函数和静态成员函数有如此显着的不同,实际上不可能处理相同的成员函数。
【解决方案2】:

对于全局(非成员)函数,函数的名称计算为该函数的地址,除非传递给 & 运算符,因此您可以(例如)分配给指向函数的指针或没有& 等效:

int f() {}

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

所以,在这种情况下,两者之间确实没有区别。

对于成员函数1,然而,规则有点不同。在这种情况下,& 是必需的;如果您尝试省略 &,代码将无法编译(无论如何,假设编译器功能正常)。

没有什么特别的原因必须是这种情况——这就是 Bjarne 决定事情应该如何。如果他决定希望成员函数的名称评估为指向成员的指针(相当于非成员函数的工作方式),他可以这样做。


1. 除了静态成员函数,它的作用大多类似于非成员函数。

【讨论】:

  • “这没有特别的原因”可能是答案的关键点。我想 OP 一直在问他自己(或她自己)这个问题。
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 2011-05-17
    • 2010-12-12
    • 1970-01-01
    • 2018-07-01
    • 2017-06-23
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    相关资源
    最近更新 更多