我无法理解以下情况。它是关于在派生类中使用基于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中) 。但是,如果我将默认构造函数显式添加到Bar
,main()
正确编译/构建。
class Foo
{
public:
virtual ~Foo();
};
struct X;
class Bar : public Foo
{
public:
Bar();
~Bar();
private:
std::unique_ptr<X> _d;
};
我没有看到此类层次结构中默认构造函数的存在与struct X
中std::unique_ptr<X>
的上下文中Bar
的完整性之间的对应关系。有人可以解释或指出可能已经存在的解释吗?
答案 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]
当你自己声明构造函数时,实例化不会发生,因为构造函数只是声明并因此在稍后的时间点链接,编译器会愉快地吃掉你的代码。