Visual c++ c++;:“崩溃说”;纯虚拟称为;
{使用Visual Studio 2010,Win7}Visual c++ c++;:“崩溃说”;纯虚拟称为;,visual-c++,Visual C++,{使用Visual Studio 2010,Win7} class Base { public: Base() : terminateCondition(false) { //spawn new thread and set entry point to newThreadFunc() } virtual ~Base() // edited to say it's virtual.
class Base
{
public:
Base() : terminateCondition(false)
{
//spawn new thread and set entry point to newThreadFunc()
}
virtual ~Base() // edited to say it's virtual.
{
terminateCondition=true;
//wait for thread to join
}
virtual void vfunc() = 0;
static void __stdcall newThreadFunc(void *args)
{
while(!terminateCondition)
pThis->vfunc();
}
volatile bool terminateCondition;
};
class Derived : public Base
{
public:
virtual void vfunc()
{
//Do Something
}
};
Derived* dPtr=new Derived; //now assume pThis is dptr
//later somewhere
delete dPtr;
此代码崩溃,称为
纯虚拟调用
。将terminateCondition=true
移动到Derived
的析构函数可防止此崩溃。我想我部分了解原因。销毁与构造的顺序相反,因此首先执行派生的
的任务,并在调用基本的
任务之前销毁派生的
的所有功能。同时,如果遇到pThis->vfunc()
,应用程序将崩溃。它称为纯虚拟。我不明白这部分。有人能解释一下吗?您的基类析构函数需要是虚拟的
,因为它不是此代码调用的未定义行为
参考资料:C++03标准:第5.3.5/3节: 如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,且静态类型应具有虚拟析构函数或行为未定义
当您通过构造函数/析构函数调用虚拟函数时,动态分派不会像您期望的那样工作。
构造函数/析构函数中的
this
的类型与正在执行构造函数/析构函数的类的类型相同。虽然您希望动态分派调用覆盖的派生类方法derived::vfunc()
,但它最终会调用Base::vfunc()
,该方法没有定义,因此会导致未定义的行为
参考资料:C++03标准10.4/6: “成员函数可以从抽象类的构造函数(或析构函数)调用;直接或间接地对纯虚拟函数进行虚拟调用(10.3)对从此类构造函数(或析构函数)创建(或销毁)的对象的影响尚未定义。”
您的基类析构函数需要是
虚拟的
,因为它不是此代码调用的未定义的行为
参考资料:C++03标准:第5.3.5/3节: 如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,且静态类型应具有虚拟析构函数或行为未定义
当您通过构造函数/析构函数调用虚拟函数时,动态分派不会像您期望的那样工作。
构造函数/析构函数中的
this
的类型与正在执行构造函数/析构函数的类的类型相同。虽然您希望动态分派调用覆盖的派生类方法derived::vfunc()
,但它最终会调用Base::vfunc()
,该方法没有定义,因此会导致未定义的行为
参考资料:C++03标准10.4/6: “成员函数可以从抽象类的构造函数(或析构函数)调用;直接或间接地对纯虚拟函数进行虚拟调用(10.3)对从此类构造函数(或析构函数)创建(或销毁)的对象的影响尚未定义。”
这是因为在代码中,当
Base::Base()
尚未完成或Base::~Base()
已启动时,可以调用vfunc
。这两种情况都将调用未定义的行为,通常表现为“纯虚拟调用”错误。
这是一个错误的原因是“虚拟”机制直到大多数派生对象的类的构造函数开始运行后才生效,而“虚拟”机制在大多数派生对象的类的析构函数完成运行后不再有效。因此,当在对象上执行构造函数或析构函数时调用虚函数时,将调用构造函数或析构函数所执行的类的相应函数。如果该函数恰好是纯虚函数,则行为是未定义的
ISO/IEC 14882:2003,10.4/6:
成员函数可以从抽象类的构造函数(或析构函数)调用;制作的效果
直接或间接为正在创建的对象对纯虚拟函数的虚拟调用(10.3)(或
未定义此类构造函数(或析构函数)中的这是因为在代码中,
vfunc
可以在Base::Base()
尚未完成或Base::~Base()
已启动时调用。这两种情况都将调用未定义的行为,通常表现为“纯虚拟调用”错误。
这是一个错误的原因是“虚拟”机制直到大多数派生对象的类的构造函数开始运行后才生效,而“虚拟”机制在大多数派生对象的类的析构函数完成运行后不再有效。因此,当在对象上执行构造函数或析构函数时调用虚函数时,将调用构造函数或析构函数所执行的类的相应函数。如果该函数恰好是纯虚函数,则行为是未定义的
ISO/IEC 14882:2003,10.4/6:
成员函数可以从抽象类的构造函数(或析构函数)调用;制作的效果
直接或间接为正在创建的对象对纯虚拟函数的虚拟调用(10.3)(或
来自这样一个构造函数(或析构函数)的(已销毁)是未定义的。这将帮助您。。请注意,不要对线程之间共享的数据使用
volatile
。在这里使用原子数据类型。@mhasan:谢谢,我会看的it@usta:哦,好的。你能给我一个提示吗。我没有完全理解你。这里的volatile有什么问题吗?例如,看看这里:T