1

我在 Code Project 上看到了这篇文章,该文章讨论了使用抽象接口作为从 C++ DLL 导出整个类的替代方法,以避免名称损坏问题。作者Release()在他的接口定义中有一个方法,应该由用户调用以在使用后释放类对象的资源。为了自动调用此方法,作者还创建了一个类似的类,该类在删除对象之前std::auto_ptr<T>调用该方法。Release()

我想知道以下方法是否可行:

#include <memory>

#if defined(XYZLIBRARY_EXPORT) // inside DLL
#   define XYZAPI   __declspec(dllexport)
#else // outside DLL
#   define XYZAPI   __declspec(dllimport)
#endif  // XYZLIBRARY_EXPORT

// The abstract interface for Xyz object.
// No extra specifiers required.
struct IXyz
{
    virtual int Foo(int n) = 0;

    //No Release() method, sub-class' destructor does cleanup
    //virtual void Release() = 0;

    virtual ~IXyz() {}
};

// Factory function that creates instances of the Xyz object.
// Private function, do not use directly
extern "C" XYZAPI IXyz* __stdcall GetXyz_();

#define GetXyz()      std::auto_ptr<IXyz>( GetXyz_() )

当然,GetXyz()可以是在头文件中定义的全局函数而不是#define. 这种方法的优点是我们不需要自己制作auto_ptr调用该Release()方法的派生词。

谢谢你的回答,阿什。

4

3 回答 3

3

通过这样做,您可能会在一个不是由对 new() 的匹配调用创建的对象上调用 delete(在您的进程中,在 auto_ptr 的析构函数中)(这是在工厂函数内部完成的,因此在 dll 内部)。保证有问题,例如当您的 dll 在发布模式下编译而调用进程处于调试模式时。

Release() 方法更好。

于 2010-07-08T18:09:03.263 回答
2

这正是 COM 的工作原理。如果您已经针对 Win32 API,请避免重新发明这个轮子。使用智能指针存储 COM 接口指针在 Windows 编程中很常见,它们的析构函数调用 Release() 方法。查看 MSDN 文档以获取 _com_ptr_t 和 CComPtr 的想法。

于 2010-07-08T18:24:18.750 回答
1

如果这是一个公共 API,您面临的限制是不同模块将链接到的 CRT,并且创建对象的 CRT 也需要是删除它的 CRT。

如果您没有选择正确的 CRT,将会出现一团糟 任何共享内存管理都应该使用 CRT(或其他内存分配)作为外部库 - 即。MSVC:多线程 DLL (/MD)

鉴于此,那么甚至不需要子类来实现您的目的。

于 2010-07-08T20:04:02.067 回答