析构函数小结
析构函数在以下3种情况时被调用:
- 1. 对象生命周期结束被销毁时
- 2. delete指向对象的指针时,或者delete指向对象的基类类型的指针,而基类析构函数是虚函数
- 3. 对象A是对象B的成员,B的析构函数被调用时,对象A的析构函数也会被调用
类声明:
class A { protected: int age; public: virtual void print(); A(int ); ~A(); }; class B : public A { public: void print(); B(int); ~B(); }; class C { private: A a; public: C(A temp); ~C(); };
类定义:
A::A(int t):age(t) { cout << "constructor A!" << endl; } void A::print() { cout << "print A!" << endl; } A::~A() { cout << "destructor A!" << endl; } B::B(int t):A(t) { cout << "constructor B!" << endl; } void B::print() { cout << "print B!" << endl; } B::~B() { cout << "destructor B!" << endl; } C::C(A temp):a(temp) { cout << "constructor C!" << endl; } C::~C() { cout << "destructor C!" << endl; }
测试1:
int main() { A* a1; return 0; }
从运行结果可以看出,声明指针并不会调用构造函数,也不会调用析构函数。
测试2:
int main() { A a(10); return 0; } //结果constructor A! //destructor A!
生命周期结束的时候,自动调用析构函数。
测试3:
int main() { B b(10); return 0; }
//结果
constructor A!
constructor B!
destructor B!
destructor A!
生成派生类时,先调用基类的构造函数,再调用派生类构造函数。析构函数调用顺序与构造函数调用顺序相反,类似于栈的先进后出原则。
测试4:
int main() { B* b = new B(10); return 0; }
//结果
constructor A!
constructor B!
对象使用new创建分配的时候,系统不会自动调用析构函数。所以,此时要手动调用析构函数。
测试5:
int main() { B* b = new B(10); delete b; return 0; }
//结果
constructor A!
constructor B!
destructor B!
destructor A!
使用delete,显示调用析构函数。
测试6:
int main() { C c(A(20)); return 0; }
//结果
constructor A!
constructor C!
destructor A!
destructor C!
destructor A!
当A对象是C的成员,C的析构函数调用时,也会调用A的析构函数。运行结果中A的析构函数比构造函数多运行一次,是因为在参数传递时,会调用A的复制构造函数(未显示定义,调用默认的复制构造函数)。