为什么C++不按运行时类型销毁对象?

Why doesn't C++ destruct the object by run-time type?

本文关键字:对象 类型 运行时 C++ 为什么      更新时间:2023-10-16

,据我所知,当基类具有虚拟函数时,C 可以获取对象动态类型的准确信息。

class Base
{
public:
    Base() {}
    ~Base() { std::cout << "Base Destructed" << std::endl; }
    virtual void f() {}
};
class Derived : public Base
{
public:
    Derived() {}
    ~Derived() { std::cout << "Derived Destructed" << std::endl; }
};
void PrintTypeName(Base *p)
{
    std::cout << typeid(*p).name() << std::endl;
}
int main()
{
    Base *p = new Derived();
    PrintTypeName(p);
    delete p;
}

上面的代码可以打印正确的对象类型,但是为什么它不能调用正确的驱动器。

我在G 和Windows编译器上测试了它,它们给出了相同的结果。我知道如果我制造基本驱动器virtual,它可以正确地破坏。

,但我想知道为什么不通过typeid调用破坏者。

如果未将方法标记为virtual,则不会存储在虚拟表中。在这种情况下,驱动器不会存储在虚拟表中。因此无法称呼。

使用当前代码, vtables 将看起来像这样:

vtable for Derived:
        .quad   0
        .quad   typeinfo for Derived
        .quad   Base::f()
vtable for Base:
        .quad   0
        .quad   typeinfo for Base
        .quad   Base::f()

请参阅演示此处

如果destructor在Base中标记为virtual,则 vtables 将看起来像这样:

vtable for Derived:
        .quad   0
        .quad   typeinfo for Derived
        .quad   Derived::~Derived() [complete object destructor]
        .quad   Derived::~Derived() [deleting destructor]
        .quad   Base::f()
vtable for Base:
        .quad   0
        .quad   typeinfo for Base
        .quad   Base::~Base() [complete object destructor]
        .quad   Base::~Base() [deleting destructor]
        .quad   Base::f()

请参阅演示此处

如果您打算从中派生类,请务必记住要制作基类驱动器virtual

在基类中将其虚拟标记将告诉编译器,它也要在删除基本对象时也要破坏派生对象。

class Base
{
public:
    Base() {}
    virtual ~Base() { std::cout << "Base Destructed" << std::endl; }
    virtual void f() {}
};

但是要注意的是,您不会将虚拟的功能放在函数面前,而您不打算覆盖。因为这附带了维护虚拟表的额外成本。

https://www.crashhandler.com/2019/03/make-destructors-destroy-virtally.html这是我对此的博客文章。