假设我有两个类:
"Foo.h"
#pragma once
class Foo
{
public:
Foo()
{
};
~Foo()
{
};
};
"A.h"
#pragma once
#include <memory>
class Foo;
class A
{
public:
A(){};
~A(){};
std::unique_ptr<Foo> foo;
};
A拥有一个unique_ptr
指向Foo
。我不想在"A.h"中包含Foo
,所以我使用前置声明。仅仅在"A.h"中使用类Foo
的前置声明,我会得到一个编译时错误:
error C2027: use of undefined type 'Foo'
error C2338: can't delete an incomplete type
我正在阅读这篇关于如何避免这个错误的文章,并将A的析构函数移动到它自己的.cpp文件中,其中我也包含了Foo:
"A.cpp"
#include "A.h"
#include "Foo.h"
A::A()
{
}
A::~A()
{
}
在"A.cpp"实现了A的析构函数后,我能够编译程序,因为Foo类在"A.cpp"中已知。这似乎是合理的,因为unique_ptr需要完整的类型才能调用它的析构函数。但令我惊讶的是,在注释掉A的构造函数后(包括"A.h"和"A.cpp"),我得到了同样的错误。这怎么可能?为什么编译器会抱怨不能调用Foo的析构函数,而A没有构造函数呢?
编辑: 我上传了4个文件,所以你可以测试这个程序。 我正在使用Visual Studio 2013的MSVC++。
A
会有一个构造函数:编译器会为其提供一个默认构造函数,并且该构造函数会得到一个内联定义。 - dypunique_ptr
,可能是因为构造函数的主体(或另一个成员)抛出异常并且需要再次销毁unique_ptr成员。您上面展示的代码不应该有这种影响,因为没有其他成员。 - Jonathan Wakelyunique_ptr
成员之后定义了其他类成员,并且构造其中一个成员可能会因为异常而失败,那么unique_ptr成员就需要被销毁。你展示的是你正在测试的确切代码,还是一个简化版本,实际上并没有给出相同的错误? - Jonathan Wakely