说明
对于基类继承类的构造函数和析构函数的执行顺序为:
构造函数
- 基类的构造函数
- 继承类的构造函数
析构函数
- 继承类的析构函数
- 基类的析构函数
为什么需要将基类的析构函数指定为 virtual 呢?
因为当用基类的指针指向一个继承类对象时,在 delete 基类指针时,如果不将析构函数指定为 virtual,则实际只有基类的析构函数会被调用,而继承类的析构函数不会被执行。所以当继承类中有资源需要在析构函数中释放时,会造成内存泄露等。
带有 virtual 的基类析构函数实例
#include <iostream>
class Something { public: Something() { std::cout << "2"; } virtual ~Something() { std::cout << "2"; } };
class Base { public: Base() { std::cout << "1"; } virtual ~Base() { std::cout << "1"; } };
class Derived : public Base { public: Derived() { std::cout << "3"; } ~Derived() override { std::cout << "3"; }
private: Something m_dataMember; };
int main() { Base *ptr{new Derived{}}; delete ptr; }
|
此时程序的输出为
输出结果表示先执行基类的构造函数,然后执行继承类成员的初始化,然后执行继承类的构造函数;接着执行继承类的析构函数,继承类成员的释放,基类的析构函数
不带 virtual 的基类析构函数实例
#include <iostream>
class Something { public: Something() { std::cout << "2"; } virtual ~Something() { std::cout << "2"; } };
class Base { public: Base() { std::cout << "1"; } ~Base() { std::cout << "1"; } };
class Derived : public Base { public: Derived() { std::cout << "3"; } ~Derived() { std::cout << "3"; }
private: Something m_dataMember; };
int main() { Base *ptr{new Derived{}}; delete ptr; }
|
此时程序的输出为
输出结果表示先执行基类的构造函数,然后执行继承类成员的初始化,然后执行继承类的构造函数;接着执行基类的析构函数