我刚刚开始学习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
答案 0 :(得分:5)
问题是main函数返回时,main中的MyThread对象会被销毁,这可能发生在新线程实际调用其Start方法之前。
作为销毁过程的一部分,在调用基类析构函数之前,vtable将被重置为基类的vtable,因此当稍后RunWrapper调用运行时,它最终会触发纯虚方法错误。在被破坏的对象上调用方法会导致未定义的行为,因此可能会发生任何事情;这种行为是C ++编译器如何实现析构函数和堆栈分配的意外。
答案 1 :(得分:0)
不确定直接导致错误的是什么,但你所做的是坏事:你的MyThread对象在线程访问之前可能超出范围。在线程开始处理时,范围完全有可能并且指针无效。
尝试在堆上分配您的对象,并查看它是否有效(然后,假设确实如此,找出在线程完成时如何释放对象)。
哦,你会想要下一步退出你的应用程序(从main返回),直到你的线程也完成...
答案 2 :(得分:-2)
问题是你正在调用属于Thread类的Start。然后,此方法调用Run,它将调用Thread类的Run方法。不幸的是,你不能从基类调用覆盖的方法。