使用std :: thread时c ++ 11意外的多态行为

时间:2014-05-02 17:58:18

标签: c++ multithreading c++11 polymorphism pure-virtual

基于C++ polymorphism with variadic function parameter我尝试编写类似的(非模板化,带构造函数)程序

代码:

#include <thread>
#include <iostream>
#include <vector>

class Base
{
public:
    Base (int count) { run(count); } // this-> does not help

    virtual void run (int count) { // non-virtual does not help eighter
        for (int i=0; i<count; ++i)
            threads.emplace_back(std::ref(*this));
    }

    virtual ~Base () {
        for (auto& t : threads)
            t.join();
    }

    virtual void operator() () = 0;

protected:
    std::vector< std::thread > threads;
};


class Derived : public Base
{
public:
    using Base::Base;
    virtual void operator() () { std::cout << "d"; }
};


int main()
{
    Derived d(4);
    std::cout << std::endl;
    return 0;
}

预期结果:

dddd

真实结果(Ubuntu 14.04,gcc v4.8.2):

pure virtual method called
pure virtual method called
terminate called without an active exception
terminate called without an active exception
dAborted (core dumped)

请注意,Derived::operator()至少曾经被称为最后一行d,几乎总是如此。

尽管代码很简单且与原始代码几乎相同(参见上面的链接),但它不起作用。我花了几个小时来解决这个问题。

目标是使用多个线程构造Derived。将执行此数量的线程(在构造函数中)并在析构函数中连接。 operator()应该用作线程体函数(如原始代码中所示)。而且,它应该是虚拟的,以提供多态性。

至于我关注的run传递*this(由于某种原因)输入为Base,而不是Derived,因此线程执行{{1}这是纯粹的虚拟

其他问题:是否有任何方式标记Base::operator()受保护?

有人可以帮帮我吗?感谢。

编辑:

根据Billy ONeal的回答,我重写了代码,因此operator()构造函数调用了Derived,但没有成功

run

结果随着时间的推移而变化 - 这是我所有的一切

#include <thread>
#include <iostream>
#include <vector>

class Base
{
public:
    virtual void run (int count) { // non-virtual does not help eighter
        for (int i=0; i<count; ++i)
            threads.emplace_back(std::ref(*this));
    }

    virtual ~Base () {
        for (auto& t : threads)
            t.join();
    }

    virtual void operator() () = 0;

protected:
    std::vector< std::thread > threads;
};


class Derived : public Base
{
public:
    Derived (int count) { run(count); }
    virtual void operator() () { std::cout << "d"; }
};


int main()
{
    Derived d(4);
    std::cout << std::endl;
    return 0;
}

尤其1) d 2) dd 3) ddd 4) dddd 5) d pure virtual method called terminate called without an active exception ddAborted (core dumped) 我无法解释。

我在5)周围添加了{...}作为匿名块,以强制在行结束程序终止之前执行析构函数,但是因为我只有

Derived d(4);

1 个答案:

答案 0 :(得分:5)

您的代码存在竞争条件(因此未定义的行为)。当您在Base的构造函数中启动线程时,线程将立即尝试在该对象上调用operator()。但是Derived的构造函数还没有运行,所以operator()仍然是来自Base的那个,它是纯虚拟的。另一个有效的执行是Base的构造函数和Derived的构造函数在线程实际开始之前完成,这会产生你期望的行为,但结果不太可能。

你对this->run没有帮助的评论是有道理的,因为输出会抱怨调用纯虚拟成员函数,而run不是纯虚拟成员,只有operator()。< / p>