为什么不能将向前声明用于std :: vector?

时间:2020-03-05 18:45:47  来源:igfitidea点击:

如果我像这样创建一个类:

// B.h
#ifndef _B_H_
#define _B_H_

class B
{
private:
    int x;
    int y;
};

#endif // _B_H_

并像这样使用它:

// main.cpp
#include <iostream>
#include <vector>

class B; // Forward declaration.

class A
{
public:
    A() {
        std::cout << v.size() << std::endl;
    }

private:
    std::vector<B> v;
};

int main()
{
    A a;
}

编译main.cpp时编译器失败。现在我知道的解决方案是" #include" B.h",但是我很好奇它为什么失败。在这件事上,g ++或者cl`的错误信息都不是非常有启发性的。

解决方案

回答

要实例化A :: v,编译器需要知道B的具体类型。

如果我们想尽量减少#included行李的数量以提高编译时间,则可以做两件事,它们实际上是彼此不同的:

  • 使用指向B的指针
  • 对B使用轻量级代理

回答

编译器在生成适当的布局信息之前需要知道" B"有多大。相反,如果我们说std :: vector &lt;B *>,则编译器将不需要知道B的大小,因为它知道指针的大小。

回答

之所以不能使用前向声明,是因为B的大小未知。

在示例中没有理由不能将B.h包含在A.h中,那么我们到底要解决什么问题?

编辑:还有另一种方法可以解决此问题:停止使用C / C ++!到了1970年代...;)

回答

它不仅仅是需要的B的大小。例如,现代的编译器会花哨的技巧来使用memcpy加快矢量副本的速度。这通常是通过部分专注于元素类型的POD来实现的。根据前向声明,我们无法判断B是否是POD。

回答

不管使用矢量还是尝试实例化一个B都无关紧要。实例化需要对象的完整定义。