Я пытаюсь дождаться, когда поток погибнет в деструкторе чистого виртуального класса. Код компилируется просто отлично и, кажется, имеет смысл. Тем не менее, следующее сообщение об ошибке при запуске его:Ожидание потока для уничтожения в деструкторе чистого виртуального класса вызывает ошибку времени выполнения
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
Вот моя программа:
#include <boost/thread.hpp>
#include <iostream>
class Test {
protected:
int x;
boost::thread th;
public:
Test(void): x(10) {};
~Test(void);
virtual void operator()(void);
void run(void);
virtual void a(void) = 0;
void wait(void);
};
Test::~Test(void) {
this->wait();
}
void Test::operator()(void) {
this->a();
x += 10;
std::cout << "Current Value: " << x << std::endl;
}
void Test::run(void) {
this->th = boost::thread(&Test::operator(), this);
}
void Test::wait(void) {
this->th.join();
}
class Test1 : public Test {
public:
virtual void a(void);
};
void Test1::a(void) {
x--;
}
main() {
Test1 test;
test.run();
//test.wait();
}
Ожидаемый результат 19. Я могу получить его, поместив вызов Test::wait()
в main()
до объекта оставляет область, а не в деструктор. Исключение не происходит, когда чисто виртуальный метод a()
удален с Test
.
Мои вопросы, то есть:
- Какой виртуальный метод ошибка со ссылкой на так
Test::a()
не в цепочке вызовов деструктора в? - Почему код компилируется, если существует такая неопределенность?
Я предполагаю, что ответ на один будет ответом на другой ...
P.S. В случае, если это имеет значение, я бегу г ++ (GCC) 4.9.1 20140903 (пререлиз) на Arch Linux, версия ядра 3.17.2-1 в GNU Баш, версия 4.3.30 (1) -release
Ничего себе. Это полностью объясняет все. Не видел этого. –
Я знал о последнем вопросе о виртуальном деструкторе. В этом конкретном случае это не изменило бы/не изменило ситуацию. Это просто интересная головоломка с чистым обходным решением. –
Конечно: 'Текущее значение: 19'. Проблема в вашем исходном коде состоит в том, что * часть объекта, содержащая реализованный 'a()' *, разрушается слишком рано, потому что только деструктор базового класса блокирует (ждет завершения потока). Если конструктор производного класса (который называется первым) блокирует, ничего плохого не происходит, потому что vtable не может быть возвращен к версии базового класса до завершения потока. Конечно, я имею в виду только явное 'wait()' в вашем 'main()', когда я говорю: «не вызывайте' wait() '. – Oguk