从 DLL 中导出前向声明 类

Exporting forward declared classes from a DLL

我想从 DLL 导出 class。它使用 Pimpl 习语,如:

#ifdef THING_EXPORT
#define THING_API __declspec(dllexport)
#else
#define THING_API __declspec(dllimport)
#endif

class thing_impl;

class THING_API thing
{
public:
    ...
private:
    thing_impl* pimpl_;
};

thing_impl 的构造函数或析构函数(或任何方法)在该 DLL 之外将不可用。我是否必须将 THING_API 放在前向声明名称 thing_impl 的前面?

Do I have to put THING_API in front of the forward declared name thing_impl?

视情况而定,但考虑到 pimpl 习语的性质,不,您不需要导出它。

您可能会收到有关未导出的警告和错误,these can be silenced 要么针对整个项目,要么将其限制在成员变量的范围内(如下所示);

class thing_impl;

class THING_API thing
{
public:
    ...
private:
    #pragma warning(push)
    #pragma warning(disable: 4251)
    thing_impl* pimpl_;
    #pragma warning(pop)
};

实现中要考虑的其他因素是将"pimpl"实现classthing_impl声明为private inside thingclass以进一步限制潜在访问权限。

class THING_API thing
{
public:
    thing(const thing&);
    thing& operator=(const thing&);
    thing(thing&&); // if needed
    thing& operator=(thing&&); // if needed
    ~thing();
    ...
private:
    class thing_impl;
    #pragma warning(push)
    #pragma warning(disable: 4251)
    thing_impl* pimpl_;
    #pragma warning(pop)
};

需要注意的一件事是当从一个DLL中导出一个class时,整个class都会被导出,所以要确保适当的复制构造函数、复制赋值运算符和析构函数(如上所述)并已实现(如果需要,还可以添加移动函数)。如果它们不存在,编译器将生成它们,并且考虑到使用 pimpl_ 成员,它们很可能不正确。为此,您还可以考虑使用 std::shared_ptr 来协助管理 pimpl_.