c ++:Crash Saying“Pure virtual called”

时间:2012-10-03 06:41:30

标签: 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.
        {
            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;

此代码崩溃说pure virtual called。将terminateCondition=true移动到Derived的析构函数可以防止此崩溃。我想我部分理解为什么。破坏与构造的顺序相反,因此Derived的执行首先执行,Derived的所有功能都被销毁,然后再调用Base。在此期间,如果遇到pThis->vfunc(),应用程序将崩溃。它崩溃说纯虚拟叫。我无法理解这一部分。有人可以解释一下吗?

2 个答案:

答案 0 :(得分:4)

您的基类析构函数必须为virtual,因为不是此代码调用未定义行为

参考:
C ++ 03标准:第5.3.5 / 3节:

  

如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义。


当你通过构造函数/析构函数调用虚函数时,动态调度不会像你期望的那样工作。
构造函数/析构函数中this的类型是正在执行构造函数/析构函数的类的类型。虽然您希望动态调度调用覆盖的派生类方法Derived::vfunc(),但它最终会调用Base::vfunc()而没有定义,从而导致未定义行为

参考:
C ++ 03标准10.4 / 6:

  

“可以从抽象类的构造函数(或析构函数)调用成员函数;对于正在创建(或销毁)的对象,直接或间接地对纯虚函数进行虚拟调用(10.3)的效​​果构造函数(或析构函数)未定义。“

答案 1 :(得分:2)

发生这种情况是因为代码vfunc可以在Base::Base()尚未完成或Base::~Base()已启动时调用。这两种情况都会调用未定义的行为,通常表现为“纯虚拟调用”错误。 它是一个错误的原因是,在大多数派生对象的类的构造函数开始运行之后,“虚拟”机制才会启动,并且在大多数派生对象的类的析构函数完成后,“虚拟”机制不再生效运行。因此,当在对象上执行构造函数或析构函数时调用虚函数时,将调用构造函数或析构函数正在执行的类的相应函数。如果该函数恰好是纯虚函数,则行为未定义。

ISO / IEC 14882:2003,10.4 / 6: 可以从抽象类的构造函数(或析构函数)调用成员函数;制作的效果 虚拟调用(10.3)直接或间接为正在创建的对象的纯虚函数(或

。来自这样的构造函数(或析构函数)是未定义的