【问题标题】:Forward declarations that involve std::vector, etc涉及 std::vector 等的前向声明
【发布时间】:2011-10-25 20:51:18
【问题描述】:

我经常使用前向声明;它们有助于避免许多#includes,缩短编译时间等等。但是如果我想在标准库中前向声明一个类呢?

// 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&lt;int&gt;,一切都会好起来的,我不再需要在我的头文件中使用#include &lt;vector&gt;

这种技术有很大的缺点吗?能够转发声明vector 的收益是否超过了它们?

【问题讨论】:

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


    【解决方案1】:

    如果您曾经将VectorOfNumbers 删除为std::vector&lt;int&gt;(并且由于您使用了公共继承,此转换是隐式的),您就进入了未定义行为的领域。这可能比人们想象的更可能是偶然发生的。

    我个人从未注意到仅在需要的地方包含 vector 会显着降低编译速度,但如果您真的想隔离包含,请使用不了解底层容器类型的客户端 API 接口 (vector ) 并将 vector 包含在单个源文件中。

    【讨论】:

      【解决方案2】:

      我不会这样做的原因:

      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! 
      

      【讨论】:

      • VectorOfNumbers 不能简单地从它的底层 std::vector 类型提供一个转换 ctor 吗?
      • @Martin:它会复制整个事情。你不想要这个,是吗?
      【解决方案3】:

      您在头文件中包含&lt;vector&gt;&lt;vector&gt; 标头将被构建以防止多次包含,因此您只需将它包含在您需要的任何地方。

      【讨论】:

      • 这如何回答 OP 的问题?
      【解决方案4】:

      这适用于类的接口,但不适用于实现。如果你的类有任何vector 成员,你必须#include &lt;vector&gt; 否则类定义将无法编译。

      【讨论】:

        【解决方案5】:

        您可以使用组合来代替继承:

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

        但我认为这并不值得。

        【讨论】:

          猜你喜欢
          • 2015-09-11
          • 2016-01-17
          • 2010-09-07
          • 1970-01-01
          • 2014-06-21
          • 2011-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多