问题描述
|
编辑:显然问题还不够明确。我遇到的问题是,在标头中定义析构函数时,它会添加到多个.obj文件中,并且链接程序会抱怨。实际的问题是:
当我将析构函数添加到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可能无法正常工作。
解决方法
问题在于,始终会调用基类析构函数-但是在这种情况下,您已经将其设为纯虚拟的,因此它不存在。使析构函数成为纯虚拟的唯一原因是在没有其他成员时将类强制为抽象。在所有情况下都需要定义一个类的析构函数。
编辑:我误读了您的代码。只需内联定义析构函数即可。
virtual ~ISplitter() {}
这里不需要任何纯虚拟成员,因为您已经有其他纯虚拟成员。
, Sharptooth的答案是正确的,因为您必须为纯虚拟析构函数提供定义(请参阅此GotW)。但这是错误的,因为你不能写
virtual ~A() = 0 {};
根据标准中的此子句(尽管许多编译器支持此扩展)
C ++ 03的10.4条第2款告诉我们什么是抽象类,并附带说明以下内容:
[注意:函数声明不能同时提供纯说明符和定义
—尾注] [示例:
struct C {
virtual void f() = 0 { }; // ill-formed
};
(末例)
有关更多详细信息,请参见我的问题