确定一个方法是否是纯虚拟的(c++)

Determine if a method is pure virtual (c++)

本文关键字:虚拟 c++ 是否是 一个 方法      更新时间:2023-10-16

有没有办法在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指出,有一个有趣的想法:

  • 使基类和派生类的析构函数受到保护,因此不能调用delete
  • 使基类的析构函数成为虚拟的
  • 在基类Delete()中实现,它首先终止线程,然后调用析构函数(调用虚拟派生的析构函数)

你在这里找错了树——在一个正确的C++程序中,不可能调用纯虚拟函数(因为试图调用它会被编译器标记为错误),所以不需要在运行时确定函数是否是纯虚拟的。

有时你会得到"纯虚拟函数调用"错误的原因是你的程序有缺陷——特别是,它受到竞争条件的影响,你的Run()方法正在调用一个正在被销毁的对象上的方法。

这里需要做的是确保线程已经退出(通过要求线程退出,然后调用pthread_join(或其他类似的API,它将阻塞,直到线程100%退出),然后销毁线程在运行时可能访问的任何对象。只有在线程死后才开始清理,这样就可以避免竞争条件,从而避免错误/崩溃。

请注意,将pthread_join()调用放在BaseClass的析构函数方法中是不起作用的,因为当BaseClass析构函数运行时,对象的子类层已经被破坏。在删除BaseClass是其超类的对象之前,您需要清理线程。(当然,在C++中自动执行该序列有点尴尬,因为AFAICT必须确保调用方手动调用预删除线程关闭函数;特别是没有简单/自动/透明的方法来自动生成预销毁线程关闭代码)

是否有一种可移植且干净(周围没有标志)的方法来实现这一点?。。。或者上面的设计出了什么问题?

可移植且干净的方法是在线程终止之前防止对象被破坏。这可以通过类TheradUtil通过适当类型的智能指针来拥有或共享BaseClass的所有权来实现。