【发布时间】:2011-09-04 17:03:31
【问题描述】:
编辑:显然这个问题的表述不够清楚。我遇到的问题是,当在标头中定义析构函数时,它会被添加到多个 .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,这可能不起作用。
【问题讨论】:
-
请贴出真实代码。答案是将析构函数定义移动到一个.cpp文件中。
-
@Neil:或者首先使析构函数不是纯虚拟的。为什么不只是一个空的虚拟析构函数?
-
@Wouter 我们不需要查看原始代码,但我们需要查看说明问题的真实 C++ 代码。例如,这里
ISplitter::ISplitter()我假设缺少~? -
@Neil:我很抱歉,它遗漏了这一点,这是一个严重错误。道歉并修复。
标签: c++ memory-leaks linker-errors virtual-destructor