虚拟方法&这个指针

时间:2010-10-01 00:12:58

标签: c++ linux pthreads

我刚刚开始学习C ++,我正在尝试使Thread类具有Java Thread类的基本功能。我要做的是创建一个你子类的类,编写一个Run方法(在基类中是纯虚拟的)创建一个子类的对象,在它上面调用start方法并且你有线程。

问题在于,在我使用C ++的方式中,调度没有正确完成 - 就像Run函数不是虚函数一样,调用了基类的Run方法。

以下是标题

的代码
#ifndef _THREAD_H_
#define _THREAD_H_

#include <pthread.h>

class Thread {
 public:
  Thread();

  void Start();

  ~Thread();

 protected:
  virtual void Run() = 0;

 private:
  static void *RunWrapper(void *);

  pthread_t thread;
};

#endif

实施

#include "thread.h"

#include <pthread.h>

Thread::Thread() {
}

void Thread::Start() {
  pthread_create(&thread, NULL, Thread::RunWrapper, (void *) this);
}

void *Thread::RunWrapper(void *arg) {
  Thread *t = (Thread *) arg;
  t->Run();
  return arg;
}

Thread::~Thread() {
  pthread_join(thread, NULL);
}

实际尝试做某事的文件

#include <iostream>

#include "thread.h"

class MyThread : public Thread {
 protected:
  void Run() {
    std::cout << "The thread is runned" << std::endl;
  }
};

int main(void) {
  MyThread thread;
  thread.Start();
  return 0;
}

我在过去10小时内遇到的错误是:

pure virtual method called
terminate called without an active exception

3 个答案:

答案 0 :(得分:5)

问题是main函数返回时,main中的MyThread对象会被销毁,这可能发生在新线程实际调用其Start方法之前。

作为销毁过程的一部分,在调用基类析构函数之前,vtable将被重置为基类的vtable,因此当稍后RunWrapper调用运行时,它最终会触发纯虚方法错误。在被破坏的对象上调用方法会导致未定义的行为,因此可能会发生任何事情;这种行为是C ++编译器如何实现析构函数和堆栈分配的意外。

答案 1 :(得分:0)

不确定直接导致错误的是什么,但你所做的是坏事:你的MyThread对象在线程访问之前可能超出范围。在线程开始处理时,范围完全有可能并且指针无效。

尝试在堆上分配您的对象,并查看它是否有效(然后,假设确实如此,找出在线程完成时如何释放对象)。

哦,你会想要下一步退出你的应用程序(从main返回),直到你的线程也完成...

答案 2 :(得分:-2)

问题是你正在调用属于Thread类的Start。然后,此方法调用Run,它将调用Thread类的Run方法。不幸的是,你不能从基类调用覆盖的方法。