有没有办法在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中执行它(特别是如果有许多派生类).
是否有便携和干净(没有标志)的方式来实现这个?...或者上述设计有什么问题?
编辑: - - - - - - - - - -
正如一些人所指出的那样,纯虚拟并不是真正的问题.它正在进入基类的析构函数,线程仍在运行.实际的问题可能是," 有没有办法在基类中使用预析构函数方法? "
In 是否有任何自动化方法来实现post-constructor和pre-destructor虚方法调用?Jeremy Friesner指出,有一个有趣的想法:
使基类和派生类的析构函数受到保护,因此无法调用delete.
使BaseClass的析构函数成为虚拟的.
在基类中实现Delete()首先终止线程,然后调用析构函数(调用虚拟派生析构函数)
Jeremy Fries.. 8
你在这里咆哮错误的树 - 在正确的C++程序中,不可能调用纯虚函数(因为调用它的尝试将被编译器标记为错误),因此无需确定在运行时,函数是否是纯虚函数.
有时你得到"纯虚函数调用"错误的原因是因为你的程序有问题 - 特别是它遇到了一个竞争条件,你的Run()方法正在调用一个正在处理的对象上的方法被摧毁.
你需要做的是确保线程已退出(通过要求线程退出,然后调用pthread_join()(或其他等效的API,将阻塞直到线程100%消失)在销毁线程可能在运行时访问的任何对象之前.只有在线程死亡后才开始清理,这样就可以避免竞争条件,从而避免错误/崩溃.
请注意,将pthread_join()调用放在BaseClass的析构函数方法中是行不通的,因为在BaseClass析构函数运行时,对象的子类层已经被销毁.在删除BaseClass为超类的对象之前,需要清理线程.(授予它在C++中自动执行该序列有点尴尬,因为AFAICT你必须确保调用者手动调用预删除线程关闭函数;特别是没有简单/自动/透明的方法来自动生成pre -destructor线程关闭代码)
你在这里咆哮错误的树 - 在正确的C++程序中,不可能调用纯虚函数(因为调用它的尝试将被编译器标记为错误),因此无需确定在运行时,函数是否是纯虚函数.
有时你得到"纯虚函数调用"错误的原因是因为你的程序有问题 - 特别是它遇到了一个竞争条件,你的Run()方法正在调用一个正在处理的对象上的方法被摧毁.
你需要做的是确保线程已退出(通过要求线程退出,然后调用pthread_join()(或其他等效的API,将阻塞直到线程100%消失)在销毁线程可能在运行时访问的任何对象之前.只有在线程死亡后才开始清理,这样就可以避免竞争条件,从而避免错误/崩溃.
请注意,将pthread_join()调用放在BaseClass的析构函数方法中是行不通的,因为在BaseClass析构函数运行时,对象的子类层已经被销毁.在删除BaseClass为超类的对象之前,需要清理线程.(授予它在C++中自动执行该序列有点尴尬,因为AFAICT你必须确保调用者手动调用预删除线程关闭函数;特别是没有简单/自动/透明的方法来自动生成pre -destructor线程关闭代码)