【发布时间】:2017-11-21 19:02:13
【问题描述】:
我正在编写一个库。它的布局看起来类似于这样:
/////////
// A.h //
/////////
#include <vector>
class B;
class A
{
std::vector<B> Bs;
public:
...
};
/////////
// B.h //
/////////
class B
{
...
}
///////////
// A.cpp //
///////////
#include "A.h"
#include "B.h"
// Implementation of A follows
...
///////////
// B.cpp //
///////////
#include "B.h"
// Implementation of B follows
...
/////////////
// MyLib.h //
/////////////
#include "A.h"
如您所见,唯一可从外部访问的类型应该是A,这就是为什么B 在A.h 中被声明为不完整类型。该库本身编译得很好,但是在程序中使用它时,编译器会发出如下错误:invalid use of incomplete type B 当我尝试创建A 类型的对象时。这些错误指向vector 标头,特别是std::vector 的析构函数,它显然需要知道它持有的类型的大小才能正确释放内部存储。我认为正在发生的是编译器试图在我的程序中实例化std::vector<B>::~vector,由于上述原因而无法成功。但是,库的二进制文件中有std::vector<B>::~vector 的符号,所以我可以不用在程序中实例化它。我正在寻找一种方法来告诉编译器。我已经尝试将MyLib.h 更改为如下内容:
/////////////
// MyLib.h //
/////////////
#include "A.h"
extern template class std::vector<B>;
不幸的是这不起作用,因为extern仅适用于编译的代码生成阶段,编译器在解析时仍然会报告错误。我想也许编译器正在尝试实例化std::vector<B>::~vector,因为A 有一个隐式析构函数,所以我尝试像这样手动实现一个析构函数:
/////////
// A.h //
/////////
#include <vector>
class B;
class A
{
std::vector<B> Bs;
~A();
public:
...
};
///////////
// A.cpp //
///////////
#include "A.h"
#include "B.h"
A::~A() {}
// Further implementation of A follows
...
这也无济于事,编译器仍在尝试实例化std::vector<B>::~vector,即使现在不应在库代码之外调用它。是否有不同的方法来实现我想要的,或者最好为B 选择不同的信息隐藏方法?
【问题讨论】:
-
你不能使用不完整类型的
std::vector,这是未定义的行为。 -
A的每个构造函数(包括隐式复制/移动构造函数)都需要vector<B>的析构函数。
标签: c++ templates instantiation incomplete-type