我一直在尝试使用unique_ptr实现PIMPL惯用语法。我受到了几篇文章的启发,这些文章总是强调同一个重要点:只在实现PIMPL的类的头文件中声明析构函数,然后在.cpp文件中定义它。否则,你会得到编译错误,例如“不完整的类型bla bla”。
好吧,我按照这个规则在一个小测试中实现了它,但我仍然遇到了“不完整的类型”错误。下面是代码,非常简短。
A.hpp:
#pragma once
#include <memory>
class A
{
public:
A();
~A();
private:
class B;
std::unique_ptr<B> m_b = nullptr;
};
A.cpp:
#include "A.hpp"
class A::B
{
};
A::A()
{
}
A::~A() // could be also '= default'
{
}
main.cpp:
#include "A.hpp"
int main()
{
A a1;
return 0;
}
我采用了两种(快速而简略的)方式进行构建,结果从我的角度来看非常惊人。
首先,我在没有链接A.cpp的情况下进行了构建。
g++ -c A.cpp
到目前为止没有任何错误。
然后,我将A.cpp和main.cpp编译成可执行文件。
g++ A.cpp main.cpp -o test
这就是我遇到麻烦的地方。在这里,我遇到了著名的“不完整类型”错误:
In file included from /usr/include/c++/9/memory:80,
from A.hpp:2,
from test.cpp:2:
/usr/include/c++/9/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = A::B]’:
/usr/include/c++/9/bits/unique_ptr.h:292:17: required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = A::B; _Dp = std::default_delete<A::B>]’
A.hpp:11:28: required from here
/usr/include/c++/9/bits/unique_ptr.h:79:16: error: invalid application of ‘sizeof’ to incomplete type ‘A::B’
79 | static_assert(sizeof(_Tp)>0,
| ^~~~~~~~~~~
我知道当你想要将unique_ptr用作PIMPL习惯用法的一部分时存在的约束条件,并且我尝试过关注它们。然而,在这种情况下,我不得不承认我没有主意了(这让我感到非常烦躁)。
我是做错了什么,还是我们不能在这种情况下使用unique_ptr?
unique_ptr
,复制操作不存在。由于自定义析构函数,移动操作也不存在。 - HolyBlackCat= nullptr
有关。如果将其删除,它就可以正常工作。 - HolyBlackCat