Pimpl with unique_ptr:为什么我必须将接口构造函数的定义移动到“.cpp”?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pimpl with unique_ptr:为什么我必须将接口构造函数的定义移动到“.cpp”?相关的知识,希望对你有一定的参考价值。
只要我不将构造函数(B
)的定义移动到标头B.h
,代码就会工作。
B.h
class Imp; //<--- error here
class B{
public:
std::unique_ptr<Imp> imp;
B(); //<--- move definition to here will compile error
~B();
//// .... other functions ....
};
B.cpp
#include "B.h"
#include "Imp.h"
B::B(){ }
~B::B(){ }
Imp.h
class Imp{};
Main.cpp(编译我)
#include "B.h"
错误:删除指向不完整类型的指针 错误:使用未定义类型'Imp'C2027
我可以以某种方式理解析构函数必须移动到.cpp
,因为Imp
的结构可能被称为: -
delete pointer-of-Imp; //something like this
但是,我不明白为什么规则也涵盖了构造函数(问题)。
我读过了 :-
- Deletion of pointer to incomplete type and smart pointers
描述了析构函数需要在
.cpp
中的原因。 - std::unique_ptr with an incomplete type won't compile 警告默认的析构函数。
答案
在异常退出的情况下,构造函数需要销毁类成员。
我不认为制作构造函数noexcept
会有所帮助,尽管它应该是这样。
另一答案
可以通过以下命令生成b.cpp中的预处理,
g++ -E b.cpp >> b.preprocessed
它如下,
# 1 "b.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "b.cpp"
# 1 "b.h" 1
class Imp;
class B
{
std::unique_ptr< Imp> imp;
public:
B(){}
~B();
};
# 2 "b.cpp" 2
# 1 "imp.h" 1
class Imp
{
};
# 3 "b.cpp" 2
B::~B(){}
在这里可以清楚地看到,class Imp
的声明来自构造函数。
那么构造函数如何创建一些不存在的东西呢? (只有前向声明是不够的)并且它清楚地表明构造函数定义必须在b.cpp
文件中,以便它将在class Imp
声明之后出现并且它变为完整类型。
另一点是,我不认为这是使用疙瘩成语的正确方法。应该在源文件中声明和定义实现类,该文件不能从外部访问,而是将其保存在单独的头文件中。
以上是关于Pimpl with unique_ptr:为什么我必须将接口构造函数的定义移动到“.cpp”?的主要内容,如果未能解决你的问题,请参考以下文章
使用 std::unique_ptr 的 C++ Pimpl Idiom 不完整类型
将使用 PIMPL 习语的类存储在 std::vector 中