虚析构函数
1 目标
本文的目的是学习虚析构函数。
2 示例代码
虚析构函数在 C++ 中用于确保正确的析构函数被调用,从而防止内存泄漏。当通过基类指针删除派生类对象时,如果基类析构函数不是虚函数,只有基类的析构函数会被调用,而派生类的析构函数不会被调用,可能会导致资源没有正确释放,造成内存泄漏。
2.1 没有虚析构函数导致内存泄漏
在这个例子中,由于基类的析构函数不是虚函数,当删除基类指针时,只调用了基类的析构函数,而派生类的析构函数没有被调用,导致派生类中动态分配的内存没有被释放,造成内存泄漏。
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor" << std::endl;
}
// 非虚析构函数
~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived : public Base {
private:
int* data;
public:
Derived() {
data = new int[100]; // 动态分配内存
std::cout << "Derived constructor" << std::endl;
}
~Derived() {
delete[] data; // 释放内存
std::cout << "Derived destructor" << std::endl;
}
};
int main() {
Base* basePtr = new Derived();
delete basePtr; // 只调用基类的析构函数,派生类的析构函数不会被调用
return 0;
}
- 输出
Base constructor
Derived constructor
Base destructor
2.2 使用虚析构函数防止内存泄漏
在这个例子中,由于基类的析构函数是虚函数,当删除基类指针时,会首先调用派生类的析构函数,释放派生类中动态分配的内存,然后调用基类的析构函数,正确地释放所有资源,防止了内存泄漏。
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor" << std::endl;
}
// 虚析构函数
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived : public Base {
private:
int* data;
public:
Derived() {
data = new int[100]; // 动态分配内存
std::cout << "Derived constructor" << std::endl;
}
~Derived() {
delete[] data; // 释放内存
std::cout << "Derived destructor" << std::endl;
}
};
int main() {
Base* basePtr = new Derived();
delete basePtr; // 调用基类和派生类的析构函数
return 0;
}
- 输出
Base constructor
Derived constructor
Derived destructor
Base destructor