思路
- 虚析构函数:在虚基类
Base
中定义虚析构函数。这确保在通过基类指针删除对象时,会调用正确的派生类析构函数,从而释放派生类中动态分配的内存。
- 遵循资源获取即初始化(RAII)原则:对于派生类中动态分配的内存,使用智能指针(如
std::unique_ptr
或 std::shared_ptr
)来管理,这样在对象析构时,智能指针会自动释放所管理的资源。
- 多重继承场景处理:在菱形继承结构或更复杂的多层继承结构中,确保每个派生类的析构函数正确调用其直接基类的析构函数。由于虚基类只会被初始化一次,所以虚基类的析构函数也只会被调用一次,并且是在最底层派生类析构时调用。
代码示例
#include <iostream>
#include <memory>
class Base {
public:
// 虚析构函数
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived1 : virtual public Base {
private:
// 使用 std::unique_ptr 管理动态分配的内存
std::unique_ptr<int[]> data1;
public:
Derived1(int size) : data1(std::make_unique<int[]>(size)) {
std::cout << "Derived1 constructor" << std::endl;
}
~Derived1() {
std::cout << "Derived1 destructor" << std::endl;
}
};
class Derived2 : virtual public Base {
private:
std::unique_ptr<int[]> data2;
public:
Derived2(int size) : data2(std::make_unique<int[]>(size)) {
std::cout << "Derived2 constructor" << std::endl;
}
~Derived2() {
std::cout << "Derived2 destructor" << std::endl;
}
};
class FinalDerived : public Derived1, public Derived2 {
public:
FinalDerived(int size) : Derived1(size), Derived2(size) {
std::cout << "FinalDerived constructor" << std::endl;
}
~FinalDerived() {
std::cout << "FinalDerived destructor" << std::endl;
}
};
解释
- 虚基类
Base
:定义了虚析构函数,保证在删除 Base
指针指向的对象时,能正确调用派生类析构函数。
- 派生类
Derived1
和 Derived2
:使用 std::unique_ptr
管理动态分配的数组,遵循 RAII 原则,自动释放内存。
- 最终派生类
FinalDerived
:通过多重继承从 Derived1
和 Derived2
继承,由于 Derived1
和 Derived2
虚继承自 Base
,Base
只会被初始化一次。在 FinalDerived
对象析构时,会按照正确的顺序调用 FinalDerived
、Derived1
、Derived2
和 Base
的析构函数,从而确保所有动态分配的内存都被正确释放,避免内存泄漏。