简体   繁体   English

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

[英]c++11 unexpected polymorphism beahviour when using std::thread

Based on C++ polymorphism with variadic function parameter I tried to write similar (non-templated, with constructors) program 基于带有可变参数函数参数的C ++多态性,我尝试编写类似的(非模板,带构造函数)程序

code: 码:

#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;
}

expected result: 预期结果:

dddd

real result (Ubuntu 14.04, gcc v4.8.2): 实际结果(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)

Please notice, that Derived::operator() was at least once really called ( d on the last line, almost always). 请注意,至少曾经一次真正调用过Derived::operator() (最后一行的d ,几乎总是这样)。

Even though the code is dead simple and almost same as original (see link above) it does not work. 即使代码非常简单,并且几乎与原始代码相同(请参见上面的链接),它也无法工作。 I spent literally hours solving this problem. 我花了数小时来解决这个问题。

Target is to construct Derived with a number of threads. 目标是构造具有多个线程的Derived This amount of threads will be executed (in constructor) and joined in destructor. 此数量的线程将在构造函数中执行并在析构函数中加入。 operator() should be used as thread-body function (as in the original code). 应该将operator()用作线程主体函数(如原始代码中一样)。 Moreover, it should be virtual in order to provide polymophism. 而且,它应该是虚拟的以便提供多态性。

As far as I'm concerned run passes *this (for some reason) typed as Base , not Derived , so threads execute Base::operator() which is pure virtual 就我而言, run通过*this (由于某种原因)键入为Base ,而不是Derived ,因此线程执行纯虚拟的Base::operator()

Additional question: is there any way labeling operator() protected? 附加问题:贴标签operator()有什么保护的方法吗?

Can anybody help me out? 有人可以帮我吗? Thanks. 谢谢。

EDIT: 编辑:

According to Billy ONeal 's answer I rewrote the code, so Derived constructor calls the run , but without any success 根据Billy ONeal的回答,我重新编写了代码,因此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;
}

Results vary over the time - here are all I have ever got 结果随时间而变化-这就是我所拥有的

1) d
2) dd
3) ddd
4) dddd
5) d
    pure virtual method called
    terminate called without an active exception
    ddAborted (core dumped)

Especially 5) I can't explain. 特别是5)我无法解释。

I've added {...} around Derived d(4); 我在Derived d(4);周围添加了{...} Derived d(4); as an anonymous block to force destructor execution before the endl of line end program termination, but since that I've got only 作为强制在行结束程序终止之前执行析构函数的匿名块,但是从那以后,我只有

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

Your code has a race condition (and therefore undefined behavior). 您的代码具有竞争条件(因此存在未定义的行为)。 When you start the thread in Base 's constructor, the thread will immediately try to call operator() on that object. Base的构造函数中启动线程时,线程将立即尝试在该对象上调用operator() But Derived 's constructor hasn't run yet, so operator() is still the one from Base , which is pure virtual. 但是Derived的构造函数尚未运行,因此operator()仍然是Base的构造函数,后者是纯虚拟的。 Another valid execution would be that Base 's constructor and Derived 's constructor finish before the threads actually get going, which would give the behavior you expect, but that result is unlikely. 另一个有效的执行方式是Base的构造函数和Derived的构造函数在线程实际运行之前完成,这将提供您所期望的行为,但是结果不太可能。

Your comment about this->run not helping makes sense because the output complains about a pure virtual member function being called, and run is not a pure virtual member, only operator() is. 您对this->run评论this->run因为输出抱怨调用了纯虚拟成员函数,而run不是纯虚拟成员,只有operator()是。

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

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