了解派生类中C++析构函数的行为

Understanding behavior of the C++ destructor in a derived class

本文关键字:析构函数 C++ 派生 了解      更新时间:2023-10-16

我正在阅读Stroustrup C++编程书中的一段代码。

class Vector_container : public Container {
Vector v;
public:    
// Vector_container implements Container
Vector_container(int s) : v(s) { } // Vector of s elements
~Vector_container() {}
double& operator[](int i) { return v[i]; }
int size() const { return v.size(); }    
};

作者接着说

  1. 析构函数 (~Vector_container()) 覆盖基类析构函数 (~Container())。
  2. 请注意,成员析构函数 (~Vector()) 由其类的析构函数 (~Vector_container()) 隐式调用。

关于#1,为什么覆盖发生在不同名称的函数中?

关于 #2,成员析构函数是否由类的析构函数系统地调用是一个C++功能?

如果不添加析构函数,编译器会创建一个析构函数。在您的情况下,您有一个,因此编译器不会生成一个。

是的,成员和基类在调用类的析构函数后被销毁。从 cppreference.com:

对于用户定义的析构函数

或隐式定义的析构函数,在 执行析构函数的主体,编译器调用析构函数 对于类的所有非静态非变量成员,按相反顺序排列 的声明,然后它调用所有直接的析构函数 非虚拟基类的构造顺序相反(在 轮调用其成员及其基类的析构函数, 等),然后,如果这个对象是大多数派生类,它调用 所有虚拟基础的析构函数。

1:析构函数是一个特殊的函数,名字在这里无关紧要。

2:是的,这是一个C++功能。由于v成员声明为Vector v,容器的析构函数将自动调用其成员的析构函数Vector::~Vector

关于 #1,为什么覆盖发生在不同名称的函数中?

它不是覆盖。每个类都有其 on 析构函数,可能是用户定义的,也可能不是用户定义的。如果销毁对象,则在继承层次结构中按从下到上的顺序调用每个析构函数。

重要说明:如果您有虚拟基类并使用基指针销毁对象,则必须将析构函数标记为virtual才能从下到上销毁,而不仅仅是基指针具有的类型。

关于 #2,成员析构函数是否由类的析构函数系统地调用是一个C++功能?

是的,析构函数从所有成员调用析构函数。

提示:如果成员是原始指针,则析构函数仅"销毁"指针,而不"销毁"它指向的元素。因此,您应该使用智能指针,或者注意删除您在其他地方创建的用户提供的析构函数中的所有对象。

为什么覆盖发生在不同名称的函数中?

因为它必须这样做。否则,对象销毁将不起作用。对象的基部也必须被破坏,所以这就是它的工作原理。

定义构造函数和析构函数的语法有点令人困惑,因为从技术上讲,这些东西没有名称(ref;dtor 没有特定的措辞,但同样适用于演绎推理)。您可以使用语法~<class name>(ref)引用类的析构函数,但这本身不是函数名称。这听起来像是一个完全学术上的区别,嗯,确实如此......但它可能有助于使"不同的名称覆盖"不那么令人惊讶。

我也不会称之为"覆盖",这个术语通常用于描述虚函数的工作原理。Bjarne正在松散地使用它。

成员析构函数是否C++由类的析构函数系统地调用?

答案是肯定的。想象一下,如果销毁一个对象并没有破坏它封装的成员?您每次都必须自己手动完成。这违背了自动范围界定的目的。