在C++编程过程中,随着项目的越来越大,代码也会越来越多,并且难以管理和分析。于是,在C++中就要分出了头(.h)文件和实现(.cpp)文件,并且也有了Package的概念。
对于以C起步,C#作为“母语”的我刚开始跟着导师学习C++对这方面还是感到很模糊。虽然我可以以C的知识面对C++的语法规范,用C#的思想领悟C++中类的使用。但是C#中定义和实现是都在一个文件中(其实都是在类里面),而使用C的时候也只是编程的刚刚起步,所写的程序也只要一个文件就够了。因此对于C++的Package理解以及.h文件和.cpp文件的总是心存纠结。
幸好导师有详细的PPT让我了解,一次对于Package的认识就明白多了。简单讲,一个Package就是由同名的.h和.cpp文件组成。当然可以少其中任意一个文件:只有.h文件的Package可以是接口或模板(template)的定义;只有.cpp文件的Package可以是一个程序的入口。
当然更具体详细的讲解,欢迎下载导师的教学PPT-Package来了解更多。
不过我在这里想讲的还是关于.h文件和.cpp文件
知道Package只是相对比较宏观的理解:我们在项目中以Package为编辑对象来扩展和修正我们的程序。编写代码时具体到应该把什么放到.h文件,又该什么放在.cpp文件中,我又迷惑了。
虽然Google给了我很多的链接,但是大部分的解释都太笼统了:申明写在.h文件,定义实现写在.cpp文件。这个解释没有差错,但是真正下手起来,又会发现不知道该把代码往哪里打。
于是我又把这个问题抛给了导师,他很耐心地给我详详细细地表述了如何在C++中进行代码分离。很可惜,第一次我听下了,但是没有听太懂,而且本来对C++就了解不深,所以也没有深刻的印象。
经过几个项目的试炼和体验之后,我又拿出这个问题问导师,他又一次耐心地给我讲解了一遍(我发誓他绝对不是忘记了我曾经问过同样的问题),这次我把它记录了下来。
为了不再忘记,我将它们总结在这里。
概览
非模板类型(none-template) 模板类型(template)
头文件(.h) 
全局变量申明(带extern限定符)
全局函数的申明
带inline限定符的全局函数的定义
带inline限定符的全局模板函数的申明和定义
类的定义
类函数成员和数据成员的申明(在类内部)
类定义内的函数定义(相当于inline)
带static const限定符的数据成员在类内部的初始化
带inline限定符的类定义外的函数定义
模板类的定义
模板类成员的申明和定义(定义可以放在类内或者类外,类外不需要写inline)
实现文件(.cpp) 
全局变量的定义(及初始化)
全局函数的定义
(无)
类函数成员的定义
类带static限定符的数据成员的初始化
*申明:declaration
*定义:definition
头文件
头文件的所有内容,都必须包含在
#ifndef {Filename} 
#define {Filename} 
//{Content of head file} 
#endif
这样才能保证头文件被多个其他文件引用(include)时,内部的数据不会被多次定义而造成错误
inline限定符
在头文件中,可以对函数用inline限定符来告知编译器,这段函数非常的简单,可以直接嵌入到调用定义之处。
当然inline的函数并不一定会被编译器作为inline来实现,如果函数过于复杂,编译器也会拒绝inline。
因此简单说来,代码最好短到只有3-5行的才作为inline。有循环,分支,递归的函数都不要用做inline。
对于在类定义内定义实现的函数,编译器自动当做有inline请求(也是不一定inline的)。因此在下边,我把带有inline限定符的函数成员和写在类定义体内的函数成员统称为“要inline的函数成员”
非模板类型
全局类型
就像前面笼统的话讲的:申明写在.h文件。
对于函数来讲,没有实现体的函数,就相当于是申明;而对于数据类型(包括基本类型和自定义类型)来说,其申明就需要用extern来修饰。
然后在.cpp文件里定义、实现或初始化这些全局函数和全局变量。
不过导师一直反复强调:不许使用全局函数和全局变量。用了之后造成的后果,目前就是交上去的作业项目会扣分。当然不能用自有不能用的理由以及解决方案,不过不在目前的讨论范围内。
自定义类型
对于自定义类型,包括类(class)和结构体(struct),它们的定义都是放在.h文件中。其成员的申明和定义就比较复杂了,不过看上边的表格,还是比较清晰的。
函数成员
函数成员无论是否带有static限定符,其申明都放在.h文件的类定义内部。
对于要inline的函数成员其定义放在.h文件;其他函数的实现都放在.cpp文件中。
数据成员
数据成员的申明与定义都是放在.h文件的类定义内部。对于数据类型,关键问题是其初始化要放在什么地方进行。
对于只含有static限定符的数据成员,它的初始化要放在.cpp文件中。因为它是所有类对象共有的,因此必须对它做合适的初始化。
对于只含有const限定符的数据成员,它的初始化只能在构造函数的初始化列表中完成。因为它是一经初始化就不能重新赋值,因此它也必须进行合适的初始化。
对于既含有static限定符,又含有const限定符的数据成员,它的初始化和定义同时进行。它也是必须进行合适的初始化
对于既没有static限定符,又没有const限定符的数据成员,它的值只针对本对象可以随意修改,因此我们并不在意它的初始化什么时候进行。
模板类型
C++中,模板是一把开发利器,它与C#,Java的泛型很相似,却又不尽相同。以前,我一直只觉得像泛型,模板这种东西我可能一辈子也不可能需要使用到。但是在导师的强制逼迫使用下,我才真正体会到模板的强大,也真正知道要如何去使用模板,更进一步是如何去设计模板。不过这不是三言两语可以讲完的,就不多说了。
对于模板,最重要的一点,就是在定义它的时候,编译器并不会对它进行编译,因为它没有一个实体可用。
只有模板被具体化(specialization)之后(用在特定的类型上),编译器才会根据具体的类型对模板进行编译。
所以才定义模板的时候,会发现编译器基本不会报错(我当时还很开心的:我写代码尽然会没有错误,一气呵成),也做不出智能提示。但是当它被具体用在一个类上之后,错误就会大片大片的出现,却往往无法准确定位。
因此设计模板就有设计模板的一套思路和方式,但是这跟本文的主题也有偏。
因为模板的这种特殊性,它并没有自己的准确定义,因此我们不能把它放在.cpp文件中,而要把他们全部放在.h文件中进行书写。这也是为了在模板具体化的时候,能够让编译器可以找到模板的所有定义在哪里,以便真正的定义方法。
至于模板类函数成员的定义放在哪里,导师的意见是放在类定义之外,因为这样当你看类的时候,一目了然地知道有那些方法和数据;我在用Visual Studio的时候查看到其标准库的实现,都是放在类内部的。
可能是我习惯了C#的风格,我比较喜欢把它们都写在类内部,也因为在开发过程中,所使用的编辑器都有一个强大的功能:代码折叠。
当然还有其他原因就是写在类外部,对于每一个函数成员的实现都需要把模板类型作为限定符写一遍,把类名限定符也要写一遍。

C++的头文件和实现文件分别写什么相关推荐

  1. Linux找头文件规则,linux 头文件、库文件查找顺序

    linux 头文件.库文件查找顺序 默认分类 2009-11-14 01:24:28 阅读126 评论0 字号:大中小 linux 头文件.库文件查找顺序 2009-11-03 12:36 Inclu ...

  2. 【转】头文件和库文件区别

    头文件提供声明,库文件提供定义/实现. C 代码的编译过程: 预处理(需要头文件) -> 编译 -> 汇编 -> 链接(需要库文件); 执行时可能还有动态链接过程. 编译的时候,只要 ...

  3. .h头文件 .lib动态链接库文件 .dll 动态链接库

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够 ...

  4. linux+C环境下动态管理头文件和库文件

    本文共分三个部分:首先给出了一个简单的Makefile的例子,然后分别详细阐述了头文件和库文件的相关知识 1.一个Makefile的例: -L是指定链接时搜索路径,比如-L./等: -l是指定具体的库 ...

  5. C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?

    著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:余天升 链接:http://www.zhihu.com/question/20630104/answer/15722407 ...

  6. Linux下gcc编译中关于头文件与库文件搜索路径相关问题

    如何指定GCC的默认头文件路径 网上偶搜得之,以之为宝:) 原地址:http://blog.chinaunix.net/u/28781/showart.php?id=401631 ========== ...

  7. .h头文件 .lib库文件 .dll动态链接库文件关系

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够 ...

  8. C程序背后的故事--头文件、库文件的查找

    文章目录 1 C程序中头文件.库文件的查找 1.1 头文件有什么用 1.2 C文件有什么用 1.3 头文件在哪里 1.4 printf函数在哪里 1.5 如何指定自己的库 1 C程序中头文件.库文件的 ...

  9. 头文件和库文件的区别

    头文件中有函数的申明,库文件实现函数的定义. 比如,printf函数.使用时应包括stdio.h,打开stdio.h你只能看到,printf这 个函数的申明,却看不到printf具体是怎么实现的,而函 ...

  10. C语言的头文件和库文件(函数库)

    C语言的头文件和库文件(函数库) 分类: Unix环境高级编程 2011-04-17 14:37 2576人阅读 评论(1) 收藏 举报 语言cgcclinuxunix 在C语言中,头文件提供对常量的 ...

最新文章

  1. BZOJ 1194: [HNOI2006]潘多拉的盒子 [DP DFA]
  2. 1091 Acute Stroke (30 分)【难度: 一般 / bfs】
  3. 信息系统项目管理师范围管理
  4. android版本sdk api对应,Android API Level与sdk版本对照表
  5. 多角度分析,通讯时序数据的预测与异常检测挑战
  6. 网络黑客节庆狂欢 趋势科技见招拆招
  7. 一建机电实务教材电子版_一建案例学不透?新版一建机电案例一本通,6大模板案例高清讲解...
  8. stata 亚组分析_手把手教你用R的gemtc包对分类变量进行贝叶斯网状Meta分析
  9. 服务器显卡驱动重装系统,windows7旗舰版系统重装显卡驱动的方法
  10. 化工原理少学时答案解析_化工原理(少学时)题库 及答案
  11. bps和pps各自是什么意思?
  12. 图片复制word java_java poi实现word导出(包括word模板的使用、复制表格、复制行、插入图片的使用)...
  13. 腾讯兔小巢是什么?零代码如何连接企业微信机器人
  14. Xshell4连接Linux后 win快捷键锁屏
  15. Reso | mysql、SQLServer、Oracle的区别
  16. Linux: pam
  17. dns服务器配置(本地dns,自己当服务器,自己测试自己)
  18. 项目管理十大知识领域和五大过程组
  19. 【bootstrap教程】Bootstrap 工具提示(Tooltip)插件
  20. 墨云saas系统总结

热门文章

  1. 《Web前端开发修炼之道》-读书笔记CSS部分
  2. Web前端开发学习误区,你掉进去了没?
  3. Animate.css介绍
  4. spring boot(一)入门
  5. javascript事件与event对象的属性
  6. Floyd算法应用-医院选址问题
  7. php yii2 获取表里最大的id_Yii2中自带分页类实现分页
  8. 华为杯大学生计算机软件大赛,关于举办2018年西安电子科技大学程序设计网络赛暨第十六届“华为杯”大学生程序设计竞赛的通知...
  9. 周期均方根和有效值的区别_黑猪肉和白猪肉有啥区别?
  10. 上传文件到华为云云服务器,上传文件到云服务器