“чистый виртуальный метод, названный” при реализации повышения:: интерфейс обертки потока

У меня есть маленькая обертка, которые централизуют то, что относительно потоков:

class Thread {
protected:
    boost::thread *m_thread;

    virtual void work() = 0;

    void do_work() {
        work();
    }

public:
    Thread() : m_thread(NULL) {}
    virtual ~Thread() {
        catch_up();
        delete m_thread;
    }

    inline void catch_up() {
        if(m_thread != NULL) {
            m_thread->join();
        }
    }

    void run() {
        m_thread = new boost::thread(boost::bind(&Thread::do_work, boost::ref(*this)));
    }
};

Когда я реализую его, говорю со следующим:

class A : public Thread {
    void work() {}
};

В:

A a; a.run();

Я получил завершение во время выполнения с симпатичным "чистым виртуальным методом, названным" отображенным. Я думаю, что это - повышение:: свяжите аргумент, но я не знаю, как сказать "Использование виртуальная чистая реализация"...

Спасибо заблаговременно.

С уважением,

Господин Mystère

6
задан Mister Mystère 1 July 2010 в 18:17
поделиться

2 ответа

Ваш сбой происходит только тогда, когда ваша программа немедленно завершает работу: он вызывает деструктор класса A, который завершает и вызывает деструктор потока до того, как вновь запущенный поток имел шанс быть запланированным. Затем поток вызывает вашу виртуальную функцию, но класса A больше не существует, поэтому он пытается вызвать do_work () потока, которая вызывает чистую виртуальную работу (). Вот ваша программа с дополнительными выходными данными:

run() started 
run() ended
~A() started
~A() ended
~Thread() started
catch_up() started
do_work() started
pure virtual method called

Стандартно, я думаю, это поведение undefined, потому что время жизни объекта уже закончилось (начался вызов деструктора) при ссылке на него ( boost :: ref (* this) ) использовалась для вызова do_work () из потока.

Решение: позвольте вашему потоку выполняться, прежде чем вы уничтожите свой объект:

A a; a.run();
a.catch_up();

Или, как говорится в документации boost.thread, «пользователь Boost.Thread должен убедиться, что упомянутый объект переживет вновь созданный поток выполнения. "

6
ответ дан 17 December 2019 в 00:03
поделиться

Я тут рискну, но подозреваю, что проблема в деструкторе потока:

virtual ~Thread() { 
    catch_up(); 
    delete m_thread; 
} 

Если поток еще не запущен, вызов catch_up () в деструкторе будет запускать поток ускорения, используя vtable Thread, а не A, как в C ++ в точке деструктора vtable соответствует области видимости типа деструктора, а не самой производной vtable.

1
ответ дан 17 December 2019 в 00:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: