有没有办法在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中执行它(特别是如果有许多派生类)。
是否有可移植且干净(没有标记)的方式来实现这个?...或者上述设计有什么问题?
修改:--------------------
有些人已经注意到,纯虚拟并不是真正的问题。它正在进入基类的析构函数,线程仍在运行。实际的问题可能应该是,“有没有办法在基类中使用析构前方法?”
在杰里米弗里斯纳指出的Is there any automated way to implement post-constructor and pre-destructor virtual method calls?中,有一个有趣的想法:
答案 0 :(得分:7)
你在这里咆哮错误的树 - 在正确的C ++程序中,不可能调用纯虚函数(因为调用它的尝试将被编译器标记为错误),所以没有需要在运行时确定函数是否为纯虚函数。
你得到“纯虚函数调用”错误的原因有时是因为你的程序有问题 - 特别是,它遇到了一个竞争条件,你的Run()方法正在调用一个对象上的方法被摧毁的过程。
你需要做的是确保线程已经退出(通过要求线程退出,然后调用pthread_join()(或者其他类似的API),这将阻塞直到线程100%消失了在之前销毁线程可能在运行时访问的任何对象。只有在线程死亡后才开始清理,这样你就可以避免竞争条件和因此错误/崩溃。
请注意,将pthread_join()调用放在BaseClass的析构函数方法中是行不通的,因为在BaseClass析构函数运行时,对象的子类层已经被销毁。在删除BaseClass为超类的对象之前,需要清理线程。 (授予它在C ++中自动执行该序列有点尴尬,因为AFAICT你必须确保调用者手动调用预删除线程关闭函数;特别是no easy/automatic/transparent way to automate the generation of the pre-destructor thread-shutdown code)
答案 1 :(得分:0)
是否有可移植且干净(没有标记)的方式来实现这个?...或者上述设计有什么问题?
便携和干净的方法是在线程终止之前防止对象被破坏。这可以通过类TheradUtil来实现,通过适当类型的智能指针拥有或共享BaseClass
的所有权。