如果我有课程' Bar':
// bar.h
class Bar
{
public:
Bar() { }
};
我转发声明在另一个类中使用std :: unique_ptr' Foo':
// foo.h
#include <memory>
class Bar;
class Foo
{
public:
Foo();
private:
std::unique_ptr<Bar> bar_;
};
我的定义包含在Foo的实现文件中:
// foo.cpp
#include "foo.h"
#include "bar.h"
Foo::Foo()
: bar_(new Bar)
{ }
我收到编译时错误&#34;&#39; sizeof&#39;的无效应用程序不完整的类型&#39; Bar&#39;&#34;。
我从here和here了解到,为了解决这个问题,我可以在foo.h中声明Foo的析构函数并将其空定义移动到foo.cpp。我不明白的是,为什么要修复它。我读到std :: unique_ptr有时需要知道其类型的完整定义。如果我必须从bar.h包含Bar以便unique_ptr看到它的定义,那对我来说是有意义的。但是,Foo的析构函数与Bar的可见性有什么关系?为什么在foo.h中声明~Foo()并在foo.cpp中定义它会使错误无效?
答案 0 :(得分:8)
unique_ptr<Bar>
的析构函数在Bar::~Bar
拥有delete
时调用Bar
。因此~unique_ptr<Bar>
需要查看Bar::~Bar
。
但模板方法仅在使用时实例化。
唯一的ptr被Foo
中的Foo::~Foo
破坏。如果~Foo
生活在可以看到~Bar
定义的地方,那么一切都很好。
如果你让它由编译器生成,那么它“存在”Foo
的声明中,它无法看到~Bar
。
如果您转发声明,请在Foo::~Foo() = default
之后在Foo::~Foo() {}
文件中执行.cpp
或#include <bar.h>
,它可以在~Bar
处看到~std::unique_ptr<Bar>
Bar
被称为`,一切都很好。
这在实践中很重要,因为销毁~Bar
的方式会有所不同,具体取决于Bar
是否为虚拟,~Bar
是否有父母,{{1}}是私有/受保护的打电话可能是违法的。