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

时间:2019-04-19 16:51:49

标签: c++ std-function

我有一个需要获取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吗?

2 个答案:

答案 0 :(得分:1)

这是C ++,因此您必须担心寿命。您的问题完全忽略了生命。那是一件坏事。

每当您谈论C ++中的任何内容时,都必须清楚所涉及的所有内容的生命周期。一种明确的方法是谈论所有权。另一件事是说一件事是谈论范围。

寿命:

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

f及其副本不清楚。如果f并且所有副本都不会超过foo的出口,则与f或副本可能超过foo的结尾是完全不同的。 / p>

部分原因不是您的错; 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是否需要在外面使用? *ptr的副本有意义吗,还是f的{​​{1}}副本之间共享所有权?更多的所有权问题及其答案将改变对您的问题的正确解决方案。

在一个更完美的世界中,*ptrfunctionmoveonly_function将会全部存在,您的选择将为您提供所需的信息,并简化隔离。

答案 1 :(得分: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