纯虚析构函数应该在哪里声明?

发布于 2024-11-10 14:13:19 字数 1260 浏览 3 评论 0原文

编辑:显然这个问题表述得不够清楚。我遇到的问题是,当在标头中定义析构函数时,它会添加到多个 .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,这可能不起作用。

EDIT: Apparently the question is not clearly formulated enough. The issue I am having is that when the destructor is defined in the header it gets added into multiple .obj files and the linker complains. The actual question is:

When I add the destructor to a CPP file in a DLL project and use the dll with dynamic loading and the interface header file, does the base destructor still get called to prevent leaking memory?

I am using MSVC 10.0 and have a DLL project that implements an interface. The interface is an abstract (pure virtual) base class. The idea is that the header is used with dynamic loading of the library. Therefore, I have used a pure virtual destructor to make sure the destructor in the base class gets called. Here is sample code to explain this:

//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 */
}

And the main implementation header

//CSplitter.h
#pragma once
#include "CHelper.h"
#include "ISplitter.h"


class CSplitter : public ISplitter {
private:
    CHelper hlp;
public:
    ~CSplitter();
    void useful();
}

Some helper class

//CHelper.h
#pragma once
#include "ISplitter.h" // I need the struct

// Class definition should go here but is irrelevant

Now the problem is that the linker generates an error that tells me the destructor: ISplitter::~ISplitter(void) has been multiply declared and the system will not build.
Error:

CHelper.obj : error LNK2005: "public: virtual __cdecl ISplitter::~ISplitter(void)" (??1ISplitter@@UEAA@XZ) already defined in CSplitter.obj

What is the correct way to fix this? I have placed the destructor in ISplitter.cpp, but I am worried this may not work if I dynamically load the library and upcast the base class to ISplitter.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

固执像三岁 2024-11-17 14:13:19

问题是基类析构函数总是被调用 - 但在这种情况下,您已将其设置为纯虚拟的,因此它不存在。将析构函数设置为纯虚拟的唯一原因是在没有其他成员时强制类为抽象类。在所有情况下都需要定义类的析构函数。

编辑:我误读了你的代码。只需实际上内联定义析构函数即可。

virtual ~ISplitter() {}

这里不需要任何纯虚拟成员,因为您已经有了其他纯虚拟成员。

The problem is that the base class destructor always gets called- but in this case, you've made it pure virtual, so it doesn't exist. The only reason to make a destructor pure virtual to is to enforce a class to be abstract when you have no other members. The destructor of a class needs to be defined in all cases.

Edit: I mis-read your code. Just define the destructor virtually inline.

virtual ~ISplitter() {}

There's no need for any pure virtual here, since you already have other pure virtual members.

神仙妹妹 2024-11-17 14:13:19

Sharptooth 的答案是正确的,因为您必须为纯虚拟析构函数提供定义(参见此 GotW< /a>)。但错误在于你不能

virtual ~A() = 0 {};

按照标准中的这个子句来写(尽管很多编译器都支持这个扩展)

C++03的Clause 10.4 paragraph 2告诉我们什么抽象类是,作为旁注,如下:

[注意:函数声明不能​​同时提供纯说明符和定义
—结束注释] [示例:

struct C {
virtual void f() = 0 { }; // ill-formed
};

—结束示例]

请参阅我的这个问题了解更多详细信息

Sharptooth's answers is correct in that you HAVE to provide a definition to the pure virtual destructor (see this GotW). But it is wrong in that you cannot write

virtual ~A() = 0 {};

according to this clause in the standard (although many compilers support this extension)

Clause 10.4 paragraph 2 of C++03 tells us what an abstract class is and, as a side note, the following:

[Note: a function declaration cannot provide both a pure-specifier and a definition
—end note] [Example:

struct C {
virtual void f() = 0 { }; // ill-formed
};

—end example]

See this question of mine for more details

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文