涉及std :: vector等的前向声明

时间:2011-10-25 20:51:19

标签: c++ c++11 forward-declaration c++-standard-library

我经常使用前瞻性声明;它们有助于避免许多#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的收益能否超过它们吗?

5 个答案:

答案 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提出的问题。

但我认为这不值得。