Pimpl与派生类中的std :: unique_ptr

Mar*_*rko 2 c++ pimpl-idiom c++11

我无法理解以下情况.它是关于使用基于std::unique_ptr派生类的pimpl习语.给定一个简单的类层次结构声明如下:

class Foo
{
public:
  virtual ~Foo(); 
  //...
};

struct X;

class Bar : public Foo
{
public:
  ~Bar();
  //...

private:
  std::unique_ptr<X> _d;
};
Run Code Online (Sandbox Code Playgroud)

我只显示与我的问题相关的代码.

想象一下,类Foo是一些接口,而类'Bar'是实现它的.我想用pimpl成语Bar.析构函数是虚拟的,并在相应的cpp文件中定义.此外struct X,只有前向声明的完整定义可以在cpp中访问,因此可以实例化析构函数的Bar析构函数std::unique_ptr<X>::~unique_ptr().当我尝试创建一个实例时Bar,我希望它能够工作

int main()
{
  Bar b;
}
Run Code Online (Sandbox Code Playgroud)

相反,我得到编译错误使用未定义类型'X'后跟消息无法删除不完整类型(在Visual Studio 2013 Update 2中).但是,如果我显式添加默认构造函数Bar,则main()正确编译/构建.

class Foo
{
public:
  virtual ~Foo(); 
};

struct X;

class Bar : public Foo
{
public:
  Bar();
  ~Bar();

private:
  std::unique_ptr<X> _d;
};
Run Code Online (Sandbox Code Playgroud)

我没有看到的默认构造函数在这个类层次结构的存在和的完整性之间的对应关系struct X在上下文std::unique_ptr<X>Bar.有人可以解释或指出可能已经存在的解释吗?

Wor*_*der 6

问题是添加的默认构造函数必须在case 的构造函数中Bar调用std::unique_ptr<X>析构Bar函数抛出异常.

但是std::unique_ptr<X>::~unique_ptr()调用unique_ptr的Deleter:std::default_delete<X>- 这需要X一个完整的类型.[unique.ptr.single.dtor]

当你自己声明构造函数时,实例化不会发生,因为构造函数只是声明并因此在稍后的时间点链接,编译器会愉快地吃掉你的代码.