C++ 析构函数
1. 定义
“~”
没有参数和返回值类型的成员函数。
2. 调用
当对象消亡时,在系统收回它所占的存储空间之前,它的析构函数会自动被调用。
一般清空下不需要定义析构函数,但是,如果对象在创建后申请了一些资源并且没有归还这些资源,就要定义析构函数在对象消亡前归还这些资源。
如果类中为提供析构函数,编译程序会在需要时隐式提供一个析构函数,该析构函数负责调用成员对象类和基类的析构函数。
class A()
{
char *str;
public:
A()
{
str=NULL;
}
A(const char *p)
{
str = new char(strlen(p)+1);
strcpy(str,p);
}
~A()
{
delete []str;
str = NULL;
}
}
当包含成员对象的对象消亡时,先调用本身类的析构函数,本身类的析构函数的函数体执行完毕后,再调用成员函数对象类的析构函数(在继承中,先调用和执行自己的析构函数,然后调用成员对象类的析构函数,最后调用基类的析构函数)。如果有多个成员对象,则成员对象析构函数的调用次序与它们定义的次序正好相反。
——————
——————————
C++析构函数使用virtual的原因介绍
析构函数也可以是虚的,甚至是纯虚的。但是构造函数不能是虚的。例如:
class A { public: virtual ~A()=0; // 纯虚析构函数 };
类型需要虚析构函数的另外一个特征是该类型具有指针成员或引用成员。如果有指针成员和引用成员,则该类型通常需要实现析构函数以及拷贝操作。通常,一个实现了析构函数的类型同时也需要实现拷贝构造函数与拷贝复制函数。
作为一个经验法则:如果你有一个带有虚函数功能的类,则它需要一个虚析构函数,原因如下:
1. 如果一个类有虚函数功能,它经常作为一个基类使用。
2.如果它是一个基类,它的派生类经常使用new来分配。
3.如果一个派生类对象使用new来分配,并且通过一个指向它的基类的指针来控制,那么它经常通过一个指向它的基类的指针来删除它(如果基类没有虚析构函数,结果将是不确定的,实际发生时,派生类的析构函数永远不会被调用)。基类有虚析构函数的话,最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。
<code>当一个类打算被用作其它类的基类时,它的析构函数必须是虚的。考虑下面的例子:
/<code>
class A { public: A() { ptra_ = new char[10];} ~A() { delete[] ptra_;} // 非虚析构函数 private: char * ptra_; }; class B: public A { public: B() { ptrb_ = new char[20];} ~B() { delete[] ptrb_;} private: char * ptrb_; }; void foo() { A * a = new B; delete a; }
<code> 在这个例子中,程序也许不会象你想象的那样运行,在执行delete a的时候,实际上只有A::~A()被调用了,而B类的析构函数并没有被调用!造成内存的泄漏,这是否有点儿可怕?
如果将上面A::~A()改为virtual,就可以保证B::~B()也在delete a的时候被调用了。因此基类的析构函数都必须是virtual的。
/<code>
通过分享实用的计算机编程语言干货,推动中国编程到2025年基本实现普及化,使编程变得全民皆知,最终实现中国编程之崛起,这里是中国编程2025,感谢大家的支持。
閱讀更多 中國編程2025 的文章