【问题标题】:Using std::thread to call an overriden method from a derived class使用 std::thread 从派生类调用重写方法
【发布时间】:2014-10-23 11:56:55
【问题描述】:

我正在尝试让这样的事情起作用:

int main()
{
    class Base
    {
    public:
        Base() = default;
        virtual void print() = 0;
        void CallThread()
        {
            std::thread(&Base::print, *this);
        };
    };

    class derived1 : public Base
    {
    public:
        derived1() = default;
        void print() { printf("this is derived1\n"); }

    };
    class derived2 : public Base
    {
    public:
        derived2() = default;
        void print() { printf("this is derived2\n"); }

    };
    Base* ptr;
    ptr = new derived1();
    ptr->CallThread();

    return 0;
}

我想要发生的结果是:

这是派生出来的1。

问题是它甚至无法编译。我正在使用 VisualStudio 2013。

错误是:

错误 2 错误 C3640: 'main::Base::[thunk]: __thiscall main'::2'::Base::`vcall'{0,{flat}}' }'' : 引用的或虚拟的 必须定义本地类的成员函数

任何想法如何使这项工作?

编辑:为了清楚起见,我在线程中尝试做的事情更复杂,这只是我的程序结构的一个例子(所以 lambda 对我来说不是一个好主意)

【问题讨论】:

  • 你不能只使用 lambda 吗?
  • 不确定错误,但不应该将std::thread(&Base::print, *this); 设为std::thread(&Base::print, this);,以免创建Base 的副本?还是副本是有意的?
  • @Niall 您已经发现了问题:您无法创建抽象类的实例。 std::thread(&Base::print, *this) 尝试为线程创建Base 的副本。 std::ref 或指针是必需的。但是,一旦使用指针或引用,就会出现终身问题。另外,线程必须分离或加入,否则会抛出异常。

标签: c++ c++11 polymorphism


【解决方案1】:

你的代码很好,除了两件事:

std::thread(&Base::print, *this);

应该是:

std::thread(&Base::print, this).join(); // join & no asterisk

【讨论】:

  • 本地定义的类需要在类体内定义成员方法(即使是空的),所以virtual void print() {}(对于gcc和msvc)。也就是说,我学到了很多关于本地课程的新东西,here
  • @Niall:你混了一些东西,本地类有纯虚拟就好了,你不能做的是本地有class A{void print();}; void A::print() {}
  • 这似乎是 gcc 和 msvc 之间实现的变体。本地类必须具有在主体中声明的函数,但不能将纯说明符 =0 和定义放在一起,因此 =0 {} 不会是 allowed。我不知道... Msvc 确实接受了带有说明符和定义的代码,gcc 不接受。
  • 这对我来说几乎成功了 - 但它仍然没有用,我不得不删除纯说明符 ( = 0 ) 并在基类的重载 print() 函数上留下空括号- 成功了。
  • @DorIoushua:第 9.8.2 节:“本地类的成员函数应在其类定义中定义,如果它们被定义的话。
猜你喜欢
  • 1970-01-01
  • 2012-06-15
  • 2023-03-12
  • 1970-01-01
  • 2014-10-31
  • 2021-10-09
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
相关资源
最近更新 更多