为什么不能使用点运算符引用非静态成员函数而不调用它?

Why can't a nonstatic member function be referred to using the dot operator without calling it?

提问人:zebra14420 提问时间:11/3/2023 最后编辑:zebra14420 更新时间:11/4/2023 访问量:125

问:

请考虑以下几点

#include <iostream>
#include <functional>

class Foo {
private:
    int m_num;
    char m_letter;

public:
    explicit Foo(int a, char c)
        : m_num(a), m_letter(c)
    {}

    int const& num() const { return m_num; }
    char const& letter() const { return m_letter; }

    void do_something(void) { 
        std::cout << m_num << ", " << m_letter << "\n";
    }
};

int main(void) {
    Foo foo(7, 'z');

    // Doesn't compile
    // std::function<void(void)> member_func1 = foo.do_something; 
    
    std::function<void(void)> member_func2 = [&foo]() -> auto {
        foo.do_something();
    };

    std::function<void(Foo&)> member_func3 = std::mem_fn(&Foo::do_something);
}

如果我尝试编译已注释掉的行,错误消息很清楚:。reference to non-static member function must be called

我发现的两种解决方法用于设置 和 ,并且相当直观。member_func2member_func3

  1. 对于 ,我们创建了一个非常薄的 lambda 包装器,它通过引用捕获目标对象,并在 body 中调用我们感兴趣的对象的成员函数。member_func2

  2. 对于 ,我们利用创建一个 .这似乎也是一个包装函数,它通过引用将目标对象作为第一个参数,然后调用其成员函数,我们对其函数感兴趣。上的类型签名非常让人想起 c 样式的参数约定。member_func3std::mem_fnstd::function<void(Foo&)>operator()()member_func3

现在设置已经完成,这是我的主要观点:

如果能够写就好了

auto member_func = foo.do_something; 

而不是需要调用更大的构造(lambda 和 )。std::mem_fn

这种设计的原因是什么?标准中是否有阻止这种情况的根本原因?仅使用上一行中提供给编译器的信息在计算上是否困难甚至不可能做到这一点?

任何关于这个主题的说明都是值得赞赏的。

C++ 标准

评论

4赞 JaMiT 11/3/2023
你会为表达式分配什么类型?正如您在“变通方法”中看到的那样,正在收集两件事 -- 函数和对象。请注意,限定的函数名称使用类的名称,而不是对象的名称。foo.do_somethingFoo::do_something()foo
3赞 JaMiT 11/3/2023
嗯。。。第二个“解决方法”要求将对象作为参数提供。如果这是可以接受的,那么指向成员的指针似乎适合您。你是在拒绝还是你不知道?(这可能属于传递对成员函数的引用auto member_func = &Foo::do_something;
0赞 Brian61354270 11/3/2023
你在找吗?auto member_func = std::bind(&Foo::do_something, foo);
2赞 heap underrun 11/3/2023
如果你在不使用的情况下询问 as 的类型,那么它将是 ,这意味着 “ 是指向类的成员函数的指针,不带任何参数并返回 ”。member_funcauto member_func = &Foo::do_something;autovoid(Foo::* member_func)() = &Foo::do_something;member_funcFoovoid
1赞 Miles Budnek 11/3/2023
可悲的是,“为什么C++没有这个特性?”这个问题很难回答。通常,答案只是“没有人考虑过它,或者认为它足够重要,可以为它写一个提案”。

答:

0赞 user12002570 11/3/2023 #1

为什么不能在不调用非静态成员函数的情况下引用它?

上述假设是错误的。您可以引用(指向)成员函数而不调用它,如下所示:

struct C
{
    int foo()
    {
    return 5;
    }
};
int main()
{ 
      int (C::*ptr)() = &C::foo; //we created a pointer to member function without callig it

}

另请注意,从技术上讲,对成员的引用(而不是)是不可能的。

评论

0赞 zebra14420 11/4/2023
谢谢你的回答。根据我现在所知道的情况,我认为这个假设是错误的,所以我更新了问题的标题,使其更符合我的问题和示例代码真正提出的问题。如果我没有更改标题,我会将您的答案标记为正确,因为它非常清晰简洁,但不确定它是否与我问题的新标题相关。就目前而言,我认为@MilesBudnek在对原始问题的评论中提供了迄今为止最相关的答案。
0赞 user12002570 11/4/2023
@zebra14420 最简单的答案是(对于你的新问题和旧问题)是“因为这就是标准定义它的方式,或者更确切地说,这不是标准所说的它可以用于什么。此外,我建议不要以这样一种方式更改问题,以使您未来问题的答案无效(在答案已经发布之后)。