从DLL导出前向声明的类

时间:2016-03-01 09:10:39

标签: c++ class dll dllexport

我想从DLL导出一个类。它使用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_;
};

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

1 个答案:

答案 0 :(得分:1)

  

我是否必须将THING_API放在前面声明的名称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)
};

在实现中要考虑的其他因素是在主thing_impl类中将“pimpl”实现类thing声明为私有,以进一步限制潜在访问。

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导出类时,将导出整个类,因此请确保存在相应的复制构造函数,复制赋值运算符和析构函数(如上所示)并实施(如果需要,另外移动)。如果它们不在那里,编译器将生成它们,并且鉴于使用pimpl_成员,它们很可能不会正确。为此,您还可以考虑使用std::shared_ptr来协助管理pimpl_