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

问题描述 投票:0回答:2

我有一个需要获取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或boost做到这一点?

c++ std-function
2个回答
0
投票

你可以用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中比任何对它的引用或由它制成的副本都要长。

Live demo


1
投票

这是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); } );

并做了;范围保证(ptr超过对foo的调用,f及其副本将不会比foo更长)平均寿命被计算在内。

但是,如果foo可以保留f的副本,那么你有两个问题。首先,ptr声称在*ptr的一生中拥有独特的所有权;但f也声称拥有它想要呼叫的对象。

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

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

在一个更完美的世界中,*ptrfunctionmoveonly_function都将存在,你的选择将在这里告知你需要什么并简化解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.