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

Pimpl with unique_ptr : Why do I have to move definition of constructor of interface to ".cpp"?

只要我不将构造函数(B)的定义移动到 header 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"

Error: deletion of pointer to incomplete type
Error: use of undefined type 'Imp' C2027

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

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

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

我已阅读 :-

构造函数需要销毁class个成员,以防异常退出

我不认为制作构造函数 noexcept 会有帮助,尽管也许应该。

b.cpp 中的预处理可以通过以下命令生成,
g++ -E b.cpp >> b.preprocessed
如下,

# 1 "b.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "b.cpp"
# 1 "b.h" 1

class Imp;

class B
{
    std::unique_ptr< Imp> imp;
public:
    B(){}
    ~B();
};
# 2 "b.cpp" 2
# 1 "imp.h" 1

class Imp
{
};
# 3 "b.cpp" 2

B::~B(){}

这里很明显,class Imp的声明在构造函数之后。
那么构造函数如何创建它不存在的东西呢? (仅前向声明是不够的)并且它清楚地表明构造函数定义必须在 b.cpp 文件中,以便它在 class Imp 声明之后出现并成为完整类型。
另一点是,我不认为这是使用疙瘩成语的正确方法。实现 class 应在源文件中声明和定义,源文件不能从外部访问,而不是将其保存在单独的头文件中。