我想从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
前面?
答案 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_
。