C ++虚拟析构函数导致调用基本方法

时间:2016-06-14 15:05:54

标签: c++ multithreading polymorphism destructor virtual-functions

我写了这个简单的例子来发生什么事 我希望所有逻辑都在基类中实现,并在派生类中派生特定方法,所以:

#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>

class base
{
public:
    base() : stop(false) {}

    virtual ~base()
    {
        std::cout << "Destructor base\n"; 

        if( handle.joinable() )
        {
            stop = true;
            handle.join();
        }
    }

    void runThread() { handle = std::thread( worker, this ); }

    virtual void stopThread() { std::cout << "Base stopThread\n"; }

protected:
    std::atomic<bool> stop;

    std::thread handle;

    static void worker( base *me )
    {
        while( me->stop == false )
        {
            std::cout << "Working\n";
            me->stopThread(); // this one in called as derived
            std::this_thread::sleep_for( std::chrono::seconds(1) );
        }

        me->stopThread(); // this one is called as base
    }
};

class derived : public base
{
public:

    ~derived()
    {
        std::cout << "Destructor derived\n"; 
    }

private:
    void stopThread() { std::cout << "derived stopThread\n"; }
};

int main()
{
    derived der;
    der.runThread();

    std::this_thread::sleep_for( std::chrono::seconds(3) );
}

结果:

Working
derived stopThread
Working
derived stopThread
Working
derived stopThread
Destructor derived
Destructor base
Base stopThread <-- hmmm 

所以一切正常,除了基础析构函数 - 它调用base :: stopThread。为什么会这样?如果我把它变为纯虚拟,我会得到一个例外。

我可以通过将析构函数移动到派生类来解决这个问题,但这一点并不清楚,因为我希望所有逻辑都在基类中实现。

我哪里错了?

由于

1 个答案:

答案 0 :(得分:4)

虚方法不会在构造函数或析构函数中调度到派生程度最高的实现。这样做的原因是,当调用base的析构函数时,derived实例已被销毁。

更正式地说,正如Quentin在评论中所说,虚方法在构造函数或析构函数内调度到实例的静态类型。