提问人:zebra14420 提问时间:11/3/2023 最后编辑:zebra14420 更新时间:11/4/2023 访问量:125
为什么不能使用点运算符引用非静态成员函数而不调用它?
Why can't a nonstatic member function be referred to using the dot operator without calling it?
问:
请考虑以下几点
#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_func2
member_func3
对于 ,我们创建了一个非常薄的 lambda 包装器,它通过引用捕获目标对象,并在 body 中调用我们感兴趣的对象的成员函数。
member_func2
对于 ,我们利用创建一个 .这似乎也是一个包装函数,它通过引用将目标对象作为第一个参数,然后调用其成员函数,我们对其函数感兴趣。上的类型签名非常让人想起 c 样式的参数约定。
member_func3
std::mem_fn
std::function<void(Foo&)>
operator()()
member_func3
现在设置已经完成,这是我的主要观点:
如果能够写就好了
auto member_func = foo.do_something;
而不是需要调用更大的构造(lambda 和 )。std::mem_fn
这种设计的原因是什么?标准中是否有阻止这种情况的根本原因?仅使用上一行中提供给编译器的信息在计算上是否困难甚至不可能做到这一点?
任何关于这个主题的说明都是值得赞赏的。
答:
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 最简单的答案是(对于你的新问题和旧问题)是“因为这就是标准定义它的方式,或者更确切地说,这不是标准所说的它可以用于什么。此外,我建议不要以这样一种方式更改问题,以使您未来问题的答案无效(在答案已经发布之后)。
评论
foo.do_something
Foo::do_something()
foo
auto member_func = &Foo::do_something;
auto member_func = std::bind(&Foo::do_something, foo);
member_func
auto member_func = &Foo::do_something;
auto
void(Foo::* member_func)() = &Foo::do_something;
member_func
Foo
void