我正在阅读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(); }
};
作者然后说
- 析构函数(
~Vector_container()
)覆盖基类析构函数(~Container()
)。- 请注意,成员析构函数(
~Vector()
)是由其类的析构函数(~Vector_container()
)隐式调用的。
关于#1,为什么在具有不同名称的函数中发生覆盖?
关于#2,成员析构函数由类的析构函数系统调用是C ++的功能吗?
答案 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 ++的功能吗?
当然。想象一下,销毁一个对象没有销毁它封装的成员吗?您每次必须手动进行。这违背了自动范围设定的目的。