Pimpl with unique_ptr:为什么我必须将接口构造函数的定义移动到" .cpp"?

时间:2017-02-23 13:13:21

标签: c++ unique-ptr pimpl-idiom

只要我不将构造函数(B)的定义移到标题B.h,代码就可以运行文件。

B.h

class Imp;  //<--- error here
class B{
    public:
    std::unique_ptr<Imp> imp;
    B();     //<--- move definition to here will compile error
    ~B();
    //// .... other functions ....
};

B.cpp

#include "B.h"
#include "Imp.h"
B::B(){ }
~B::B(){ }

Imp.h

class Imp{};

Main.cpp (编译我)

#include "B.h"
  

错误:删除指向不完整类型的指针
  错误:使用未定义的类型&#39; Imp&#39; C2027

我可以以某种方式理解析构函数必须移到.cpp,因为可能会调用Imp的结构: -

delete pointer-of-Imp;  //something like this

但是,我不明白为什么规则也涵盖了构造函数(问题)。

我读过: -

2 个答案:

答案 0 :(得分:8)

构造函数需要销毁类成员,如果它以异常退出。

我不认为使构造函数noexcept有所帮助,但也许应该有所帮助。

答案 1 :(得分:-1)

此问题与错误地使用std::unique_ptr有关。如果您编写类似std::unique_ptr<std::string> uPointer的内容,则表示您希望std::unique_ptr默认删除std::string的{​​{1}}对象,并且没有专门的delete函数。

如果您使用所有标志(例如,

delete

您将收到以下错误:

$ g++ -std=c++17 -Wall -Wextra -Werror B.cpp -c

这仅表示您无法将/usr/include/c++/8/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Imp]’: /usr/include/c++/8/bits/unique_ptr.h:274:17: required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Imp; _Dp = std::default_delete<Imp>]’ forward.h:12:21: required from here /usr/include/c++/8/bits/unique_ptr.h:79:16: error: invalid application of ‘sizeof’ to incomplete type ‘Incomplete’ static_assert(sizeof(_Tp)>0, 用于默认的std::unique_ptr过程,因为delete需要std::default_delete<Imp>,而sizeof()不能用于不完整输入以下内容:

https://en.cppreference.com/w/cpp/language/sizeof

这只是意味着这种方式是错误的,您应该将构造函数放在.cpp中,以便在执行构造函数时sizeof()是完整类型。

您的代码仍然可以进行少量修改即可运行,但我认为这没有用,但请查看如何删除错误并进行编译,

Imp