当我将析构函数添加到DLL项目中的CPP文件并使用动态加载的dll和接口头文件时,是否还会调用基本析构函数以防止内存泄漏?
我正在使用MSVC 10.0并且有一个实现接口的DLL项目。该接口是一个抽象(纯虚拟)基类。这个想法是标题用于动态加载库。因此,我使用了一个纯虚拟析构函数来确保调用基类中的析构函数。以下是解释此内容的示例代码:
//ISplitter.h
#pragma once
struct param {
int something;
}
class ISplitter {
public:
virtual ~ISplitter() = 0;
virtual void useful() = 0;
}
ISplitter::~ISplitter() {
/* Make sure base class destructor gets called */
}
主要实现标题
//CSplitter.h
#pragma once
#include "CHelper.h"
#include "ISplitter.h"
class CSplitter : public ISplitter {
private:
CHelper hlp;
public:
~CSplitter();
void useful();
}
一些助手类
//CHelper.h
#pragma once
#include "ISplitter.h" // I need the struct
// Class definition should go here but is irrelevant
现在问题是链接器生成一个错误,告诉我析构函数:ISplitter :: ~ISplitter(void)已被多次声明,系统将不会构建。 错误:
CHelper.obj : error LNK2005: "public: virtual __cdecl ISplitter::~ISplitter(void)" (??1ISplitter@@UEAA@XZ) already defined in CSplitter.obj
解决此问题的正确方法是什么?我已将析构函数放在ISplitter.cpp中,但我担心如果我动态加载库并将基类转发到ISplitter,这可能不起作用。
答案 0 :(得分:5)
问题是基类析构函数总是被调用 - 但在这种情况下,你已经使它成为纯虚拟的,所以它不存在。使析构函数纯虚拟的唯一原因是当没有其他成员时强制类是抽象的。在所有情况下都需要定义类的析构函数。
编辑:我误读了你的代码。只需几乎内联地定义析构函数。
virtual ~ISplitter() {}
这里不需要任何纯虚拟,因为你已经有了其他纯虚拟成员。
答案 1 :(得分:2)
Sharptooth的答案是正确的,因为您必须为纯虚拟析构函数(see this GotW)提供定义。但你不能写
是错误的virtual ~A() = 0 {};
根据标准中的该子句(尽管许多编译器支持此扩展)
C ++ 03的第10.4条第2款 告诉我们抽象类是什么,并作为旁注,以下内容:
[注意:函数声明不能同时提供纯指定符和定义 - 尾注] [例如:
struct C {
virtual void f() = 0 { }; // ill-formed
};
-end example]
有关详细信息,请参阅this question of mine