我经常使用前瞻性声明;它们有助于避免许多#include
,从而缩短编译时间。但是如果我想在标准库中转发声明一个类呢?
// Prototype of my function - i don't want to include <vector> to declare it!
int DoStuff(const std::vector<int>& thingies);
我听说禁止/不可能转发声明std::vector
。现在this answer to an unrelated question建议以这种方式重写我的代码:
stuff.h
class VectorOfNumbers; // this class acts like std::vector<int>
int DoStuff(const VectorOfNumbers& thingies);
stuff.cpp
// Implementation, in some other file
#include <vector>
class VectorOfNumbers: public std::vector<int>
{
// Define the constructors - annoying in C++03, easy in C++11
};
int DoStuff(const VectorOfNumbers& thingies)
{
...
}
现在,如果我在整个项目的所有环境中都使用VectorOfNumbers
而不是std::vector<int>
,那么一切都会很好,我的头文件中不需要#include <vector>
了!
这种技术有哪些主要缺点?能够前向声明vector
的收益能否超过它们吗?
答案 0 :(得分:6)
如果您将VectorOfNumbers
删除为std::vector<int>
(并且由于您使用了公共继承,这种转换是隐含的),您已经进入了未定义行为的领域。这可能比人们怀疑的更容易发生。
我从未亲自注意到在需要时只包含vector
的重要编译速度减慢,但是如果你真的想要隔离include,请使用不了解底层容器类型的客户端API接口({ {1}})并将vector
包含在一个源文件中。
答案 1 :(得分:3)
我不这样做的原因:
const std::vector<int>& a = a_3rd_party_lib::get_data(); // this type is out of your control
DoStuff(a); // you cannot pass it to this function!
答案 2 :(得分:0)
您在头文件中包含<vector>
。我们会构建<vector>
标题以防止多个包含,因此您只需将它包含在您需要的任何位置。
答案 3 :(得分:0)
这适用于类的接口,但不适用于实现。如果您的班级有vector
个成员,则必须#include <vector>
或类定义不会编译。
答案 4 :(得分:0)
您可以使用合成:
而不是继承// Implementation, in some other file
#include <vector>
class VectorOfNumbers
{
public:
std::vector<int>& container;
VectorOfNumbers(std::vector<int>& in_container)
: container(in_container)
{
}
};
int DoStuff(const VectorOfNumbers& thingies)
{
std::sort(thingies.container.begin(), thingies.container.end());
// ...
}
缺点是每次访问时都有额外的变量名称。
此外,您需要将此实现放在cpps包含的头文件中,以便他们知道他们可以使用VectorOfNumbers做什么。
基本上,只需为你的矢量制作一个包装器。这就像PImpl的轻量级版本(我们只关心避免标头依赖性,所以我们不需要完整的指针解耦)。它避免了Mark B和ybungalobill提出的问题。
但我认为这不值得。