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

时间:2019-07-10 11:20:07

标签: c++ inheritance destructor

我正在阅读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.   
  3. 请注意,成员析构函数(~Vector())是由其类的析构函数(~Vector_container())隐式调用的。
  4.   

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

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

4 个答案:

答案 0 :(得分:3)

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

是的,在调用类的析构函数之后,成员和基类也将被析构。来自cppreference.com

  

对于用户定义或隐式定义的析构函数,在   执行析构函数的主体后,编译器将调用析构函数   对于该类的所有非静态非变量成员,以相反的顺序   声明,然后它调用所有直接的析构函数   非虚拟基类的构造顺序相反(在   依次调用其成员及其基类的破坏者,   等等),然后,如果此对象属于派生类,则调用   所有虚拟基地的破坏者。

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

  

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

这不是替代。每个类都有其on析构函数,也许是用户定义的。而且,如果销毁了一个对象,则在继承层次结构中,从下到上的顺序将调用每个析构函数。

重要说明:如果您具有虚拟基类并使用基指针破坏了对象,则必须将析构函数标记为virtual,以便从下到上进行析构,而不仅是基指针具有的类型

  

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

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

提示:如果成员是原始指针,则析构函数仅“破坏”指针,而不是其指向的元素。因此,您应该使用智能指针,或者小心删除用户在其他位置创建的析构函数中自己的所有对象。

答案 3 :(得分:1)

  

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

因为必须这样做。否则对象销毁将不起作用。对象的基础部分也必须被破坏,这就是它的工作方式。

用于定义构造函数和析构函数的语法有点令人困惑,因为从技术上来说,这些东西没有名称 ref; dtor没有特定的措辞,但同样适用通过演绎推理)。您可以使用语法~<class name> ref引用类的析构函数,但它本身不是函数名。这听起来似乎完全是学术上的区别,但是,这是……但是,这可能有助于使“不同的名称重载”不那么令人惊讶。

我也不会将其称为“覆盖”,这是一个通常用于描述虚拟函数如何工作的术语。 Bjarne宽松地使用它。

  

类的析构函数系统地调用成员析构函数是C ++的功能吗?

当然。想象一下,销毁一个对象没有销毁它封装的成员吗?您每次必须手动进行。这违背了自动范围设定的目的。