我写了这个简单的例子来发生什么事 我希望所有逻辑都在基类中实现,并在派生类中派生特定方法,所以:
#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。为什么会这样?如果我把它变为纯虚拟,我会得到一个例外。
我可以通过将析构函数移动到派生类来解决这个问题,但这一点并不清楚,因为我希望所有逻辑都在基类中实现。
我哪里错了?
由于
答案 0 :(得分:4)
虚方法不会在构造函数或析构函数中调度到派生程度最高的实现。这样做的原因是,当调用base
的析构函数时,derived
实例已被销毁。
更正式地说,正如Quentin在评论中所说,虚方法在构造函数或析构函数内调度到实例的静态类型。