C++ 抽象类造成的内存泄漏

1. 内存泄漏实例

今天检查代码时发现一个因为使用抽象类引起的内存泄漏。相关代码简化如下:

//抽象类
class AbstratcClass {
	//省略其他代码
	virtual void do_something() = 0;
}

//实现类
class ImpClass: public AbstractClass {
	//省略其他代码
	virtual void do_something();
}

//应用类
class AppClass {
	//省略其他代码
	void work() {
		AbstractClass* p = new ImpClass();
		//省略其他代码
		delete p;		//	此处即使调用了 delete 删除抽象类指针,也无法释放实现类的内存,造成内存泄漏。
	}
}

2. 利用虚析构函数,释放实现类资源

采用虚析构函数,抽象类和实现类都定义虚析构函数,代码如下:

//抽象类
class AbstratcClass {
	//省略其他代码
	virtual ~AbstractClass(){}
	virtual void do_something() = 0;
}

//实现类
class ImpClass: public AbstractClass {
	//省略其他代码
	virtual virtual ~ImpClass(){}
	virtual void do_something();
}

//应用类
class AppClass {
	//省略其他代码
	void work() {
		AbstractClass* p = new ImpClass();
		//省略其他代码
		delete p; //因为定义了虚析构函数,所以实际上会调用 ImpClass 的析构函数。
	}
}

3. 定义接口函数,显式释放资源

增加 release() 函数,显式释放实现类资源。修改后代码如下,解决内存泄漏问题:

//抽象类
class IMyInterface {
	//省略其他代码
	virtual void release() = 0;
	virtual void do_something() = 0;
}

//实现类
class ImpClass: public IMyInterface {
	//省略其他代码
	virtual void release() {				
		delete this; //用接口函数 release 间接调用实现类的析构函数,释放资源。
	}
	virtual void do_something();
}

//应用类
class AppClass {
	//省略其他代码
	void work() {
		IMyInterface * intf = new ImpClass();
		//省略其他代码
		intf->release(); 	//通过接口函数释放资源和析构。
	}
}

这种方式在用抽象类实现纯粹的接口定义时,比较合适。我个人比较喜欢最后这个解决方案,这个方案抽象类作为一个纯粹的接口存在,自身仅包含接口函数声明,不包含任何可执行的代码。

发布了174 篇原创文章 · 获赞 80 · 访问量 35万+

猜你喜欢

转载自blog.csdn.net/quicmous/article/details/100121382