【发布时间】:2017-05-24 02:00:26
【问题描述】:
有没有办法在 C++ 中确定一个方法在运行时是否是纯虚拟的?事实上,问题是是否有办法知道派生类的析构函数是否已经执行但基类仍然存在。
这是我的情况(简化):
class BaseClass{
private:
class ThreadUtil *threadUtil;
public:
Mutex mutex;
~BaseClass(){
threadUtil->Terminate();
MutexLocker ml(mutex); // Avoid destruction during use
}
virtual Size size()=0;
};
class Derived:public BaseClass{
public:
Size size()override{return Size(100,80);}
};
class ThreadUtil{
private:
bool terminate;
BaseClass *owner;
public:
void Run(){
while(!terminate){
if (!IS_OWNER_SIZE_FN_PURE_THAT_S_THE_QUESTION){
MutexLocker ml(owner->mutex);
DoSomething(owner->size()); // Runtime error if in the dtor of BaseClass
}
}
}
};
“调用纯虚函数”运行时错误非常偶发(在执行 ~BaseClass 时调用 DoSomething。
在派生类中终止线程+锁定是安全的,但我想在 BaseClass 中执行(特别是如果有很多派生类)。
是否有一种可移植且干净(没有标志)的方式来实现这一点?...或者上述设计有什么问题?
编辑:--------------------
正如一些人所指出的,纯虚拟并不是真正的问题。它正在进入基类的析构函数,线程仍在运行。实际的问题可能应该是,“有没有办法在基类中使用预析构方法?”
在 Jeremy Friesner 指出的 Is there any automated way to implement post-constructor and pre-destructor virtual method calls? 中,有一个有趣的想法:
- 使基类和派生类的析构函数受到保护,因此无法调用 delete。
- 将 BaseClass 的析构函数设为虚拟。
- 在基类 Delete() 中实现,它首先终止线程,然后调用析构函数(调用虚拟派生析构函数)
【问题讨论】:
-
为什么你的基类析构函数不是虚拟的?
-
你不想从 dtor 调用任何虚拟函数,通常不仅仅是纯函数
-
纯虚拟在这里是一个红鲱鱼。真正的问题是
Run在对象不再存在时尝试访问它。解决方案是正确管理所有权,例如使用std::shared_ptr/weak_ptr而不是原始指针。 -
if 语句会出现与
while(!terminate)相同的问题 - 在您执行测试一纳秒后,条件可能会发生变化。保持锁定是停止非同步更改的标准方法。
标签: c++ destructor pure-virtual