对抽象类的引用不能传递给线程函数?

Reference to abstract class can't be passed to thread function?

本文关键字:线程 函数 抽象类 引用 不能      更新时间:2023-10-16

我想在使用std::thread调用的函数中使用对摘要类(A)作为参数类型的参考。似乎不可能,因为编译器出于某种原因进行编译:std::tuple<A>,即使在我的代码中,A的参考类型也被用作参数(从来没有用作值类型)。

#include <cstdlib>
#include <thread>
class A {
public:
  virtual void a() = 0;
};
class B : public A {
public:
  virtual void a() {
  }
};
class C {
public:
  C(A& aRef) {
    thread = std::thread(&C::doSomething, this, aRef);
  }
private:
  void doSomething(A& aRef) {
  }
  std::thread thread;
};
int main(int argc, char* argv[]) {
  B b;
  C c(b);
  return EXIT_SUCCESS;
}

将在Visual Studio 2017上输出:

error C2259: 'A': cannot instantiate abstract class
tuple(278): note: see reference to class template instantiation 'std::tuple<A>' being compiled
tuple(278): note: see reference to class template instantiation 'std::tuple<C *,A>' being compiled
thread(49): note: see reference to class template instantiation 'std::tuple<void (__thiscall C::* )(A &),C *,A>' being compiled
main.cpp(18): note: see reference to function template instantiation 'std::thread::thread<void(__thiscall C::* )(A &),C*const ,A&,void>(_Fn &&,C *const &&,A &)' being compiled

为什么std::thread试图编译std::tuple<A>?如果我直接从主线程调用C::doSomething,则该代码可以正常编译。

我这里有什么我缺少的吗?

当将其作为参数传递给线程时,您需要将参考包装在std::reference_wrapper中。

您可以使用std::ref()来做到这一点。

在此示例中查看:

#include <thread>
#include <utility>
#include <iostream>
struct A {
    virtual void a() = 0;
};
struct B : public A {
    virtual void a() { std::cout << "Hello Worldn"; }
};
class C {
    void doSomething(A& aRef) { aRef.a(); }
    std::thread thread;
public:
    C(A& aRef) : thread(&C::doSomething, this, std::ref(aRef)) {}
    // or alternatively using a lambda:
    //C(A& aRef) : thread( [&](){ doSomething(aRef); } ) {}
    void join() { thread.join(); }
};
int main(int argc, char* argv[]) {
    B b;
    C c(b);
    c.join();
}

以这样的编译和运行:

$ g++ ~/tt.cc -std=c++11 -pthread && ./a.out
Hello World

供参考:

  • http://en.cppreference.com/w/cpp/utility/functional/ref
  • http://en.cppreference.com/w/cpp/utility/functional/referenional/reference_wrapper