如何将对象类的方法传递为 std::function?

How can I pass a method of an object's class as std::function?

本文关键字:std function 方法 对象      更新时间:2023-10-16

我有一个函数需要获取std::function-type参数。我还有一个指向对象的抽象类型指针。是否可以仅使用对象传递该方法?

函数签名:

void foo(std::function<bool(int i)>);

类示例:

class IBase // interface
{
public:
virtual bool sampleMethod(int i) = 0;
};
class Child1 : public IBase // one of the classes that inherit from IBase
{
public:
bool sampleMethod(int i) override;
};

因此,有以下指针指向其中一个 Child 类的对象:

std::unique_ptr<IBase> ptr;

我想用它来传递 sampleMethod 作为 foo 的参数。 有没有办法使用标准或增强来做到这一点?

您可以使用std::bind和占位符执行此操作:

foo (std::bind (&IBase::sampleMethod, ptr.get (), std::placeholders::_1));

您还可以使用捕获ptr的 lambda:

foo ([&ptr] (int i) { return ptr->sampleMethod (i); });

无论哪种情况,正如 Yakk - Adam Nevraumont 所说,请确保ptrfoo中对它的任何引用或副本都长寿。

现场演示

这是C++,所以你必须担心一生。 你的问题完全忽略了一生;这是一件坏事。

每当你谈论C++任何事情时,你必须清楚所涉及的一切的生命周期。 明确这一点的一种方法是谈论所有权。 另一种是说一件事是谈论范围。

生命周期:

void foo(std::function<bool(int i)> f);

f和副本尚不清楚。 如果f和所有副本都不会活过foo的出口,那与f或副本可以活过foo结束完全不同。

部分原因不是你的错;C++std库缺少描述"没有状态所有权的可调用对象"(function_ref)的词汇类型,因此人们使用值语义std::function

假设你真正想要的是一个function_ref<void(int)>,那么你可以这样做:

foo( [&](int i){ return ptr->sampleMethod(i); } );

范围保证(ptrfoo调用更久,f及其副本不会超过foo)平均寿命。

但是,如果foo可以保留f的副本,则有两个问题。 首先,ptr声称在*ptr的整个生命周期内拥有独特的所有权;但f也声称对它想要调用的对象拥有所有权。

更重要的是,std::function可以被复制;这意味着要么它调用的对象必须被复制,要么我们被迫拥有共享所有权。

那么foo之后*ptr需要在外面可用吗?*ptr的副本是否有意义,还是*ptrf副本之间共享所有权? 更多的所有权问题及其答案会改变您问题的正确解决方案。

在一个更完美的世界里,functionmoveonly_functionfunction_ref都会存在,你的选择会告诉你在这里需要什么,并简化独。

我根据保罗的回答开始写这个:

_window.setCursorPosCallback(std::bind(&RenderWorld::mouseCallback, this, std::placeholders::_1,std::placeholders::_2));

但是叮叮当当的叫我改成这样:

_window.setCursorPosCallback([this](auto && x, auto && y) { 
mouseCallback(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y)); 
});

所以这有点酷