繁体   English   中英

多态在C ++ lambda函数中不起作用

[英]Polymorphism doesn't work in C++ lambda function

我有这样的方法:

void syncOperation(ProgressCallback& progressCallback);

其中ProgressCallback为:

class ProgressCallback
{
public:
    virtual void onProgress(std::size_t currValue, std::size_t maxValue) {}
    virtual void onDone() {}
};

并且我想使其异步,因此请执行以下操作:

void asyncOperation(ProgressCallback& progressCallback)
{
    auto impl = [this](ProgressCallback& progressCallback_)
    {
        syncOperation(progressCallback_);
    };
    jobsPool.addJob(std::bind(impl, progressCallback));
}

但是在asyncOperation(ProgressCallback&)情况下( asyncOperation(ProgressCallback&)progressCallback行为不是多态的,它始终会调用基类的方法,这绝对不是我期望的。 所以我的问题是:1)为什么会发生这种情况; 2)如何解决它(是的,我知道我可以停止使用lambda了,但是也许有一些传统的解决方法)?

您显示的代码没有多态的余地,但是让我们假设asyncOperation传递了对从ProgressCallback派生的东西的引用:

将引用传递给bind时,您正在创建一个副本。 绑定返回的对象根据其具有的类型信息存储值。 它只知道它具有对ProgressCallback的引用,因此它存储的是哪种值。 这将导致切片副本。

您需要将值包装在reference_wrapper中:

jobsPool.addJob(bind(impl, ref(progressCallback));

或者您可以使用lambda(更好):

jobsPool.addJob([impl,&progressCallback](){ impl(progressCallback); });

或者,您也可以创建impl以便它自己执行所有操作。

您现在所要做的相对相当于:

jobsPool.addJob([impl,=progressCallback]() mutable { impl(progressCallback); });

您无需定义一个lambda,然后使用bind或使用两个lambda,就可以一次完成所有操作:

void asyncOperation(ProgressCallback& progressCallback)
{
    jobsPool.addJob([&] { syncOperation(progressCallback); });
}

如前所述,在原始代码中,由于正在切片切片,您被咬了。 由于模板参数推导的工作原理,像std::bind这样的延迟函数调用需要具有通过引用包装传递的按引用参数。 这种相当奇怪的行为是一旦访问lambda便根本不使用bind另一个很好的理由。 但是请注意,此行为也适用于std::thread

请注意,存储通过引用捕获某些东西的lambda是一件非常危险的事情。 您可以使用一个progressCallback对象调用asyncOperation ,然后该对象仍处于活动状态,并且有可能在执行lambda时破坏了该对象,从而导致不确定的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM