我有一个需要获取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吗?
答案 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}}副本之间共享所有权?更多的所有权问题及其答案将改变对您的问题的正确解决方案。
在一个更完美的世界中,*ptr
,function
,moveonly_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所说,请确保ptr
在foo
中的任何引用或引用的副本中均不存在。