在派生类

时间:2015-07-06 16:07:20

标签: c++ c++11 pimpl-idiom

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

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

struct X;

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

private:
  std::unique_ptr<X> _d;
};

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

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

int main()
{
  Bar b;
}

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

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

struct X;

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

private:
  std::unique_ptr<X> _d;
};

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

1 个答案:

答案 0 :(得分:5)

问题是添加到Bar的默认构造函数必须调用std::unique_ptr<X>的析构函数,以防Bar的构造函数抛出异常。

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

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