(C++)关于多文件include顺序产生环的若干心得

这工程大了,类多了,include还真是个问题。
前些天写多两个类,结果引来一堆"不是类或命名空间名称""未声明的标识符""左边必须指向/类/结构/联合/泛型类型"...哭死>_<

我们都知道,include的顺序是有讲究的。可是具体该怎么讲究平时也没太在意过,反正只要能include到程序运行起来就行了(啊,不要BS我,我是门外汉,囧)。
然则当文件一多起来,相互调用的关系难免形成环,这时就头痛了...

研究以下逻辑关系:
------------------------------------------------------------------------------------------------------
·有一个CItem,也就是物品类
·有一个CPlayer,是人物类
·还有一个CGloabal,里面定义的是静态变量,有CItem也有CPlayer,基本都是map,其作用在于从数据库读取数据存进这些map
·CPlayer要用到CItem
·CItem里面的某些方法需要读取到CGlobal里面的静态表来计算某些东西。 
-----------------------------------------------------------------------------------------------------
于是形成以下调用关系环:

即CPlayer要include CItem,CItem要include CGlobal,而CGlobal却要include CItem和CPlayer...@_@

下面给出简化的代码框架:

============================================================================

实验结果:

如果都在*.h文件里面include该类需要用到的其他类头文件,由于环的存在会造成编译器的编译顺序混乱,从而出现"不是类或命名空间名称""未声明的标识符""左边必须指向/类/结构/联合/泛型类型"……

但如果取消掉include环中的一条边,譬如上图CItem.h文件中取消#include "CGlobal.h",而在CItem.cpp中#include "CGlobal.h",则可以运行无阻。

因此,在*.cpp文件才需要用到的类,最好在*.cpp中才include,过早include可能会出现意想不到的麻烦。

---------------------------------------------------------------------------------------------------------------

然而,当*.h文件中不能避免地要产生include环,譬如上图中,假设CItem.h的类声明就要用到CGlobal类的东西,那又该如何?

师兄提供了一个权宜之计,即,将CItem类中那个要用到CGlobal类来声明的成员变量/成员函数,放在CItem.cpp里面声明,成为文件内部的全局变量……(。。我不知道这个方法是不是很山寨,囧。。)

=======================================================================

经过几天几夜不停地与"不是类或命名空间名称""未声明的标识符""左边必须指向/类/结构/联合/泛型类型"奋战……

【小结】include使用心得

0、头文件一定要#pragma once,或者使用#ifndf-#define-#endif头文件保护符;

1、类设计时尽量做到一个类一个.h文件,一个.cpp文件,有必要的话再加一个.inl文件;

2、尽量做到.h文件只做类声明,.cpp文件只做类实现——这样不仅简洁直观,还可以使include文件的位置尽可能地推后,从而减小环产生的可能性;

3、include的时候只include本文件需要的东西,只在.cpp用到的,最好在.cpp中再include;

4、有时候一些常用类会在很多地方被include,所以为图省事写一个诸如includes.h的文件来存放这些文件的include——然而这样会造成很多不必要的文件被include,当一个很原子的文件都include了这个includes.h时,编译顺序就被打乱了,形成环的可能性大大提高。so,不要为了省事写includes.h文件,除非能确定这些声明在里面的文件相互独立且足够原子,或者它们的声明顺序能严格地确定(树形),从而保证后来的文件include它们不会产生环;

5、当*.h中无可避免地要产生include环时,可以考虑把其中的一条边破坏掉,代价是把成员变量放到.cpp文件中变为全局变量;

6、如果A类的A.h文件中只是需要使用到另一个类B的指针,即诸如“B* pObjB;”,那么可以在A.h中做一个“class B;”的前置声明,而在A.cpp中才#include "B.h",这样也可以减少环的产生概率。(本条感谢mariner验证)

瑶瑶按:以上只是个人心得,各方大侠如果能提供规范的include规则,请不吝赐教,感激不尽。

 

 

转自 http://hi.baidu.com/czlaner/blog/item/a489ca6e05e3b2d381cb4aea.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值