gpt4 book ai didi

c++ - 虚拟析构函数如何在 C++ 中工作

转载 作者:可可西里 更新时间:2023-11-01 15:00:19 25 4
gpt4 key购买 nike

我将输入一个示例:

class A
{
public:
virtual ~A(){}
};

class B: public A
{
public:
~B()
{
}

};



int main(void)
{
A * a = new B;
delete a;
return 0;
}

现在在上面的示例中,析构函数将自下而上递归调用。我的问题是编译器如何执行此操作。

最佳答案

您的问题中有两种不同的魔法。第一个是编译器如何调用析构函数的最终覆盖程序,第二个是编译器如何按顺序调用所有其他析构函数。

免责声明:该标准不强制执行此操作的任何特定方式,它仅强制执行更高级别的操作行为。这些是各种实现通用的实现细节,但不是标准强制要求的。

编译器如何分派(dispatch)给最终覆盖程序?

第一个答案很简单,用于其他 virtual 函数的相同动态调度机制也用于析构函数。为了刷新它,每个对象存储一个指向其每个 vtable 的指针 (vptr)(在多重继承的情况下,可以有多个),当编译器看到对任何虚函数的调用,它按照指针的静态类型的 vptr 找到 vtable,然后使用该表中的指针转发调用。在大多数情况下,调用可以直接调度,在其他情况下(多重继承)它调用一些中间代码 (thunk) 固定 this 指针以引用类型该函数的最终覆盖

然后编译器如何调用基本析构函数?

析构对象的过程比你在析构函数体内编写的操作要多。当编译器为析构函数生成代码时,它会在用户定义的代码前后添加额外的代码。

在调用用户定义的析构函数的第一行之前,编译器会注入(inject)代码,使对象的类型成为被调用的析构函数的类型。也就是说,就在输入 ~derived 之前,编译器添加了将修改 vptr 以引用 derived 的 vtable 的代码,因此对象的运行时类型变成了 derived (*)

在用户定义代码的最后一行之后,编译器注入(inject)对成员析构函数和基析构函数的调用。这是执行禁用动态分派(dispatch),这意味着它将不再一路下降到刚刚执行的析构函数。它等效于在析构函数末尾为对象的每个基添加 this->~mybase();(按照基声明的相反顺序)。

对于虚拟继承,事情变得有点复杂,但总体上它们遵循这种模式。

编辑(忘记了 (*)):(*) §12/3 中的标准要求:

When a virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from a destructor, and the object to which the call applies is the object under construction or destruction, the function called is the one defined in the constructor or destructor’s own class or in one of its bases, but not a function overriding it in a class derived from the con- structor or destructor’s class, or overriding it in one of the other base classes of the most derived object.

该要求意味着对象的运行时类型是此时正在构造/析构的类的类型,即使正在构造/析构的原始对象是派生类型。验证此实现的简单测试可以是:

struct base {
virtual ~base() { f(); }
virtual void f() { std::cout << "base"; }
};
struct derived : base {
void f() { std::cout << "derived"; }
};
int main() {
base * p = new derived;
delete p;
}

关于c++ - 虚拟析构函数如何在 C++ 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7750280/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com