当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《为什么std::vector不能使用前向声明?》经验,为你挑选了3个好方法。

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

// B.h
#ifndef _B_H_
#define _B_H_

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

#endif // _B_H_

并像这样使用它:

// main.cpp
#include 
#include 

class B; // Forward declaration.

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

private:
    std::vector v;
};

int main()
{
    A a;
}

编译时编译器失败main.cpp.现在我知道的解决方案是#include "B.h",但我很好奇为什么它失败了.无论是g++cl的错误信息都在这个问题很有启发.



1> Curt Hagenlo..:

编译器在生成适当的布局信息之前需要知道"B"有多大.相反,如果你说std::vector,那么编译器就不需要知道B有多大,因为它知道指针有多大.


@lzprgmr:的确,`vector `可能只包含一个指向T的指针,所以我不同意Curt的回答.在不知道`B`的定义的情况下可以知道`vector `的布局,但由于`vector`是一个模板,因此必须为每个模板参数实例化其所有成员函数:你不能将它们的声明与他们的实施.由于其中一些成员函数需要`T`的定义,因此它必须是在`vector`中使用的完整类型.问题是由于成员函数是内联定义的,而不是`vector `的布局,取决于`B`的布局.
@LucTouraille:等等,这不是完全错误的答案吗?正如其他人所说,这里的问题是内联构造函数,而不是容器本身......

2> 小智..:

实际上,如果A的构造函数是在知道B类型的编译单元中实现的,那么您的示例将构建.

std :: vector实例具有固定的大小,无论T是什么,因为它包含,如前所述,只包含指向T的指针.但是vector的构造函数取决于具体类型.您的示例无法编译,因为A()尝试调用向量的ctor,如果不知道B就无法生成.这是可行的:

A的声明:

// A.h
#include 

class B; // Forward declaration.

class A
{
public:
    A(); // only declare, don't implement here

private:
    std::vector v;
};

A的实施:

// A.cpp
#include "A.h"
#include "B.h"

A::A() // this implicitly calls vector's constructor
{
    std::cout << v.size() << std::endl;
}

现在A的用户只需知道A,而不是B:

// main.cpp
#include "A.h"

int main()
{
    A a; // compiles OK
}


只是为了向您添加更多信息……Vis​​ual Studio VS2017现在可以像`gcc`一样工作并且可以正常编译。

3> Josh..:

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

如果您想尽量减少#included行李的数量以改善编译时间,那么您可以做两件事,它们实际上是彼此的变化:

    使用指向B的指针

    使用轻量级代理 B

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有