C++尽量用前置声明替代头文件包含

cat kkk.txt llll.log>fjdskl.log
grep  "fdsfdsa*" hhh.log>kkkk.txt

C++头文件重复包含
假设我们有两个类A和B,分别定义在各自的头文件A.h和B.h中,但是在A中要用到B,B中也要用到A,但是这样的写法当然是错误的:

class B;
class A
{
public:
    B b;
};

class B
{
public:
    A a;
};

因为在A对象中要开辟一块属于B的空间,而B中又有A的空间,是一个逻辑错误,无法实现的。在这里我们只需要A类中的B类型成员改成指针形式就可以避免这个无限延伸的怪圈了。为什么要更改A而不是B?因为就算你在B中做了类似的动作,也仍然会编译错误,这仅仅上一个先后顺序的问题

为什么会这样呢?因为C++编译器自上而下编译源文件的时候,对每一个数据的定义,总是需要知道定义的数据类型的大小。在预先声明语句class B;之后,编译器已经知道B是一个类,但是其中的数据却是未知的,因此B类型的大小也不知道这样就造成了编译失败,VC++6.0下会得到如下编译错误:

      error C2079: 'b' uses undefined class 'B'

二、不同头文件中的类的嵌套

为了保证头文件仅被编译一次,在C++中常用的办法是

#IFNDEF  TESTSTR
#define TESTSTR
      //很多语句
#endif

在高版本的VC++上,还可以使用这个命令来代替以上的所有:#pragma once
它的意思是,本文件内的代码只被使用一次
但是不要以为使用了这种机制就全部搞定了,比如在以下的代码中:

//文件A.h中的代码
#pragma once
#include "B.h"
class A
{
public:
    B* b;
};

//文件B.h中的代码
#pragma once
#include "A.h"
class B
{
public:
    A* a;
};

在主函数前面使用#include "A.h"之后,主要编译错误如下:
error C2501: 'A' : missing storage-class or type specifiers。仍然是类型不能找到的错误,其实这里仍然需要前置声明。分别添加前置声明之后,可以成功编译了代码形式如下:

//文件A.h中的代码
#pragma once
#include "B.h"
class B;
class A
{
public:
    B* b;
};

//文件B.h中的代码
#pragma once
#include "A.h"
class A;
class B
{
public:
    A* a;
};

这样至少可以说明,头文件包含代替不了前置声明。有的时候只能依靠前置声明来解决问题。我们还要思考一下,有了前置声明的时候头文件包含还是必要的吗?我们尝试去掉A.h和B.h中的#include行,发现没有出现新的错误
三、两点原则
头文件包含其实是一想很烦琐的工作,不但我们看着累,编译器编译的时候也很累,再加上头文件中常常出现的宏定义感觉各种宏定义的展开是非常耗时间的,远不如自定义函数来得速度。
第一个原则: 如果可以不包含头文件,那就不要包含,这时候前置声明可以解决问题,如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没有访问到类的具体成员,那么前置声明就可以了,因为指针这一数据类型的大小是特定的,编译器可以获知.
第二个原则: 尽量在CPP文件中包含头文件,而非在头文件中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值