首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用std::c++11时出现意外多态现象

使用std::c++11时出现意外多态现象
EN

Stack Overflow用户
提问于 2014-05-02 17:58:17
回答 1查看 602关注 0票数 1

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

代码:

代码语言:javascript
复制
#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;
}

预期结果:

代码语言:javascript
复制
dddd

真实结果(Ubuntu 14.04,gcc诉4.8.2):

代码语言:javascript
复制
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,因此线程执行纯虚拟的Base::operator()

附加问题:是否有任何方式标记operator()受保护?

有人能帮我吗?谢谢。

编辑:

根据Billy ONeal的回答,我重写了代码,所以Derived构造函数调用了run,但没有成功。

代码语言:javascript
复制
#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;
}

结果会随着时间的推移而变化--以下是我所得到的全部

代码语言:javascript
复制
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);作为一个匿名块,以强制在行结束程序终止的endl之前执行析构函数,但从那以后,我只得到了

代码语言:javascript
复制
pure virtual method called
terminate called without an active exception
ddAborted (core dumped)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-02 18:02:17

您的代码具有争用条件(因此没有定义行为)。当您在Base的构造函数中启动线程时,该线程将立即尝试对该对象调用operator()。但是Derived的构造函数尚未运行,因此operator()仍然是来自Base的构造函数,这完全是虚拟的。另一个有效的执行是,Base的构造函数和Derived的构造函数在线程真正开始运行之前完成,这将给出您期望的行为,但这种结果是不可能的。

您对this->run的评论没有意义,因为输出抱怨调用的是纯虚拟成员函数,而run不是纯虚拟成员,只有operator()

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23434201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档