首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在基类/派生类中称为C++的纯虚函数

在基类/派生类中称为C++的纯虚函数
EN

Stack Overflow用户
提问于 2017-08-17 15:35:56
回答 2查看 1.2K关注 0票数 3

我有这个基类:

代码语言:javascript
复制
class Base {
public:
  Base();
  virtual ~Base();
protected:
  virtual on_next_item(std::string& item) = 0;
private:
    void read_loop();
};

和这个派生类:

代码语言:javascript
复制
class Derived : public Base {
public:
  Derived();
  virtual ~Derived();
protected:
  void on_next_item(std::string& item) override;
};

Base类构造函数中,我启动了一个线程,该线程从套接字读取并调用派生类上调用的on_next_item()。在Base析构函数中,读取器线程通过一个原子标志停止。但有时read_loop仍然会调用on_next_item,我会得到一个“纯虚函数调用!”错误。我假设我是在竞态条件下运行的:

子类(对象)已被析构,因此函数不再注册。

有没有合适的方法来解决这个竞态问题?

为了完整起见,下面是阅读器循环:

代码语言:javascript
复制
while (running.load())
{
  string item = read();
  if (running.load())
  {
    on_text_item(item);
  }
}

Base类析构函数中,运行标志被切换为false。

编辑(完整的运行示例,必须执行多次才能在问题中运行):

代码语言:javascript
复制
#include <atomic>
#include <boost/thread/thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>

class Base
{
public:
  Base() : running(true)
  {
    readerThread = new boost::thread(&Base::read_loop, this);
  }

  virtual ~Base()
  {
    running = false;

    delete readerThread;
    readerThread = nullptr;
  }

protected:
  virtual void on_next_item(std::string &item) = 0;

private:
  boost::thread *readerThread;

  void read_loop()
  {
    std::string element = "Element";
    while (running.load())
    {
      boost::this_thread::sleep_for(boost::chrono::milliseconds(2));
      on_next_item(element);
    }
  }

  std::atomic_bool running;
};

class Derived : public Base
{
public:
  Derived() : Base()
  {
  }

  virtual ~Derived()
  {
  }

protected:
  virtual void on_next_item(std::string &item)
  {
    std::cout << "On Next Item " << item << std::endl;
  }
};

void constAndDestruct()
{
  Derived d;
  boost::this_thread::sleep_for(boost::chrono::seconds(2));
}

int main(int argc, char **argv)
{

  constAndDestruct();
  boost::this_thread::sleep_for(boost::chrono::seconds(2));
}

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2017-08-17 15:47:58

从构造函数或析构函数调用虚函数是generally considered a bad idea。函数调用实际上就像函数不是虚拟的一样,因为在这一点上,Derived的构造函数还没有被调用,成员变量或Derived仍然没有初始化……

显而易见的解决方案是将类的逻辑移动到公共成员函数,并在对象创建后立即调用该函数:

代码语言:javascript
复制
Derived d;
d.run();
票数 5
EN

Stack Overflow用户

发布于 2017-08-17 23:50:07

我建议做出以下改变:

  1. 在~
  2. ()而不是~Base()中将"running“标志设置为false。将" running“的访问级别更改为protected.virtual ~Derived() {running= false;}
  3. 将休眠从读取器的循环中移除,同时(running.load()) {

on_next_item(element);}

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

https://stackoverflow.com/questions/45729152

复制
相关文章

相似问题

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