在基类的析构函数中调用的虚函数的变形能力

时间:2016-08-14 10:08:11

标签: c++

#include <iostream>
#include <map>

using namespace std;
class Base
{
public:
    int m_nValue;

    Base()
    {
    }

    virtual ~Base()
    {
        Clear();
    }

    virtual void Clear()
    {
        cout << "Destroy Base." << endl;
    }
};

class Derived: public Base
{
public:
    Derived()
    {
    }

    void Clear() override
    {
        cout << "Destory Derived." << endl;
    }
};

int main()
{
    Derived* d = new Derived();
    delete d;
}

这打印&#34;销毁基地。&#34;。我是C ++的新手,任何人都可以告诉我为什么会这样?为什么不打印&#34; Destory Derived。&#34;

1 个答案:

答案 0 :(得分:1)

T类型的构造函数的主体开始执行时(之前),对象的动态类型将调整为T

这意味着虚拟调用将像对象最初创建的类型T一样解析。

这是一个相当昂贵的机制,因此它有一个非常重要的原因:避免在派生类m中调用虚拟函数实现D,其中D::m的假设为T尚未成立。这种下行呼叫是例如漏洞的常见来源。 Java的。它不可能在C ++中发生。

调用的最后一个构造函数体是派生类的构造函数体,即用于创建对象的类。这就是对象最终的动态类型。

相反,当对象被破坏时,会发生相反的情况:动态类型的一系列调整为更一般的类型。实质上,在执行类T的析构函数体时,对象的动态类型为T。就像在执行某些T构造函数的主体时一样。

注意:
¹类T的成员函数的与上下文无关的假设是关于T对象的状态的一般假设,例如其成员变量值之间的关系。这称为/类不变。因此,C ++动态类型调整机制有助于确保只有构造函数和析构函数必须处理未完全建立的类不变量:在C ++中(但不是在Java或C#中),所有其他成员函数都可以盲目地假设类不变量已经建立。 功能