C++中的头文件和源文件

一、C++编译模式       

        通常,在一个C++程序中,只包含两类文件——cpp文件和h文件。cpp文件被称作C++源文件,里面放的都是C++的源代码;h文件则被称作C++头文件,里面放的也是C++的源代码。

        C+ +语言支持“分别编译”(separate compilation)。也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里。

        cpp文件里的东西都是相对独立的,在编译(compile)时不需要与其他文件互通,只需要在编译成目标文件后再与其他的目标文件做一次链接(link)就行了。比如,在文件a.cpp中定义了一个全局函数“void a() {}”,而在文件b.cpp中需要调用这个函数。即使这样,文件a.cpp和文件b.cpp并不需要相互知道对方的存在,而是可以分别地对它们进行编译, 编译成目标文件之后再链接,整个程序就可以运行了。

 

二、C++头文件

        头文件的内容跟.cpp文件中的内容一样,都是C++源代码。但头文件不用被编译。

        我们把所有的函数声明全部放进一个头文件中,当某一个cpp源文件需要它们时,它们就可以通过一个宏命令“#include”包含进这个cpp文件中,从而把它们的内容合并到cpp文件中去。当cpp文件被编译时,这些被包含进去的h文件的作用便发挥了。

         #include的作用是把它后面所写的那个文件的内容,完完整整地、一字不改地包含到当前的文件中来。值得一提的是,它本身是没有其它任何作用与副功能的,它的作用就是把每一个它出现的地方,替换成它后面所写的那个文件的内容。简单的文本替换,别无其他。因此,main.cpp文件中的第一句(#include "math.h"),在编译之前就会被替换成math.h文件的内容。即在编译过程将要开始的时候,main.cpp的内容已经发生了改变

 

三、头文件的书写

        1、头文件中,只能存在变量或者函数的声明,而不要放定义。

        因为一个头文件的内容实际上是会被引入到多个不同的cpp文件中的,并且它们都会被编译。放声明当然没事,如果放了定义,那么也就相当于在多个文件中出现了对于一个符号(变量或函数)的定义,纵然这些定义都是相同的,但对于编译器来说,这样做不合法。

        2、头文件中可以写const对象的定义。

        因为全局的const对象默认是没有extern的声明的,所以它只在当前文件中有效。把这样的对象写进头文件中,即使它被包含到其他多个cpp文件中,这个对象也都只在包含它的那个文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。同时,因为这些cpp文件中的该对象都是从一个头文件中包含进去的,这样也就保证了这些cpp文件中的这个const对象的值是相同的,可谓一举两得。

         同理,static对象的定义也可以放进头文件。

        3、头文件中可以写内联函数(inline)的定义。

        inline函数是需要编译器在遇到它的地方根据它的定义把它内联展开的,而并非是普通函数那样可以先声明再链接的(内联函数不会链接),所以编译器就需要在编译时看到内联函数的完整定义才行。

        如果内联函数像普通函数一样只能定义一次的话,这事儿就难办了。因为在一个文件中还好,我可以把内联函数的定义写在最开始,这样可以保证后面使用的时候都可以见到定义;但是,如果我在其他的文件中还使用到了这个函数那怎么办呢?这几乎没什么太好的解决办法。

        因此C++规定,内联函数可以在程序中定义多次,只要内联函数在一个cpp文件中只出现一次,并且在所有的cpp文件中,这个内联函数的定义是一样的,就能通过编译。那么显然,把内联函数的定义放进一个头文件中是非常明智的做法。

        4、头文件中可以写类(class)的定义。

         在程序中创建一个类的对象时,编译器只有在这个类的定义完全可见的情况下,才能知道这个类的对象应该如何布局,所以,关于类的定义的要求,跟内联函数是基本一样的。所以把类的定义放进头文件,在使用到这个类的.cpp文件中去包含这个头文件,是一个很好的做法。

        值得一提的是,类的定义中包含着数据成员和函数成员。数据成员是要等到具体的对象被创建时才会被定义(分配空间),但函数成员却是需要在一开始就被定义的,这也就是我们通常所说的类的实现。

        一般的做法是,把类的定义放在头文件中,而把函数成员的实现代码放在一个cpp文件中。这是很好的办法。

        还有另一种办法,即直接把函数成员的实现代码也写进类定义里面。在C++的类中,如果函数成员在类的定义体中被定义,那么编译器会视这个函数为内联的。因此,把函数成员的定义写进类定义体,一起放进头文件中,是合法的。

        注意一下,如果把函数成员的定义写在类定义的头文件中,而没有写进类定义中,这是不合法的,因为这个函数成员此时就不是内联的了。一旦头文件被两个或两个以上的cpp文件包含,这个函数成员就被重定义了。

       5、头文件需要保护措施

        如果头文件中只包含声明语句,那么它被同一个cpp文件包含再多次都没问题。但如果头文件是上述中某种情况,定义了一些函数,在cpp文件中包含了两次头文件就麻烦了。

        使用"#define"配合条件编译可以很好地解决这个问题。在一个头文件中,通过#define定义一个名字,并且通过条件编译#ifndef...#endif使得编译器可以根据这个名字是否被定义,再决定要不要继续编译该头文中后续的内容。这个方法虽然简单,但是写头文件时一定记得写进去。


转载自:http://www.cnblogs.com/lidabo/archive/2012/04/17/2454568.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258165.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hibernate 事物隔离级别 深入探究

目录 一、数据库事务的定义 二、数据库事务并发可能带来的问题 三、数据库事务隔离级别 四、使用Hibernate设置数据库隔离级别 五、使用悲观锁解决事务并发问题 六、使用乐观锁解决事务并发问题 Hibernate事务与并发问题处理(乐观锁与悲观锁) 一、数据库…

Linked List Cycle II - LeetCode

Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note: Do not modify the linked list. Follow up:Can you solve it without using extra space? 思路:维护两个指针slow和fast。先判断是否存在环。 在判断是否…

mysql 无论输入什么都是现实 not found_NotAPanda

前言面试竞争力越来越大,是时候撸一波Vue和React源码啦;本文从20个层面来对比Vue和React的源码区别;如果需要了解API的区别,请戳:Vue 开发必须知道的 36 个技巧React 开发必须知道的 34 个技巧文章源码:请戳…

这五张PPT告诉你,如何打造无人驾驶“最强大脑”

“英特尔在谈无人驾驶,会成为汽车制造商吗?NO!我们要为无人驾驶提供从车、连接到云的‘最强大脑’。” 在昨天于北京举行的英特尔无人驾驶分享会上,英特尔无人驾驶事业部中国区市场总监徐伟杰在主旨演讲中开门见山。 这也是英特尔无人驾驶事业部去年11月…

javascript之ua与urlSchema

我们首先拿到浏览器ua: 1 var ua navigator.userAgent; 1 if (ua.indexOf("MicroMessenger") > -1) { 2 alert("微信浏览器"); 3 } 1 if (ua.indexOf("iPhone") > -1) { 2 alert("iphone"); 3 } 其…

ezdpl Linux自动化部署实战

最近把ezdpl在生产环境中实施了,再加上这段时间的一些修改,一并介绍一下。再次申明: ezdpl不是开箱即用的,需要根据自己的应用环境定制。对初学者来说使用起来反倒困难更多、风险更大。它不是一个通用的项目,更多的是提…

无法打开输入文件mysql_错误LNK1181,pip安装“无法打开输入文件”mysqlclient.lib'...

我是Python新手,正在尝试安装mysql模块,但是在解决了其他5个问题之后,我现在遇到了一个问题,当我尝试安装该模块时,会出现以下日志:PS C:\Users\poste> pip install mysqlCollecting mysqlUsing cached …

俄罗斯将封杀LinkedIn 推动个人数据本地化

北京时间11月11日上午消息,莫斯科一家法院本周四支持了在俄罗斯封杀职业社交网站LinkedIn的决定。 俄罗斯联邦通信监管局(Roskomnadzor)之前要求国内外企业从2015年9月开始,必须将所有俄罗斯用户的个人数据存储在该国境内。Linked…

python的datetime举例_Python datetime模块的使用示例

1、获取当前年月日时分秒# -*- encodingutf-8 -*-import datetimenow datetime.datetime.now()print("now:{}".format(now))year now.yearprint("year:{}".format(year))month now.monthprint("month:{}".format(month))day now.dayprint(&q…

vs2015 去除 git 源代码 绑定,改成向tfs添加源码管理

除了下文的方法是将源码管理从git改成tfs之外,还要做以下几步即可 向tfs添加源码 打开源码管理(管理连接),双击打开你要向其中添加的tfs连接选中该解决方案,右键 将解决方案添加到源码管理嵌入完毕vs2015 去除 git 源代码 绑定 第一次碰到这个…

HDU 4609 FFT

题目大意 给定n条边的边值,求任意取三条边能组成三角形的概率 这里概率 P valid/tot tot (n-2)*(n-1)*n/6是没问题的 valid表示合法的方式 先考虑,任意两条边组合形成方法的总数 因为边值在100000的范围内,这里组合用fft计算 得到最后形成和…

《日志管理与分析权威指南》一2.3 良好日志记录的标准

本节书摘来华章计算机《日志管理与分析权威指南》一书中的第2章 ,第2.3节,(美) Anton A. Chuvakin Kevin J. Schmidt Christopher Phillips 著 姚 军 简于涵 刘 晖 等译更多章节内容可以访问云栖社区“华章计算机”公众号查…

Python【01】【基础部分】- A

一、WHATS PYTHON ? 1、python 简介 Python(英语发音:/ˈpaɪθən/), 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年发明,第一个公开发行版发行于1991年。Python是纯粹的自由软件&#xff0…

java的自增自减_Java中自增和自减操作符(++/--)的那些事

自增()和自减(--)运算符在JAVA语言中存在着很多运算符,但是在实际开发中我们或许很少用到它们,在初次学习中却时常出现它们的身影,对于这些运算符的含义和用法,是否还记得呢?1. 概述自增操作符()和自减操作符(--)是对变…

Finished yeah!

终于到了最后的博客阶段,这时候才知道博客此时此刻是多么的惬意,它成了书写心声的自由平台!耗时一天完成这作业说起来也是蛮辛苦的,编译器需要新装,IDE需要熟悉,当然最主要的是之前浅入浅出的C功底在此次作…

《Python语言程序设计》——1.6 开始学习Python

本节书摘来自华章计算机《Python语言程序设计》一书中的第1章,第1.6节,作者:[美]梁勇(Y. Daniel Liang) 更多章节内容可以访问云栖社区“华章计算机”公众号查看。 1.6 开始学习Python 关键点:…

Tomcat性能调优

1、集成apache 虽然Tomcat也可以作web服务器,但是处理静态html的速度比不上apache,且其作为web服务器的功能远不如Apache,因此把apache和tomcat集成起来,讲html和jsp功能部分进行明确的分工,让tomcat只处理jsp部分&…

【转】sip中的subscribe和notify扩展应用技术

http://blog.csdn.net/hwz119/article/details/3965322转载于:https://www.cnblogs.com/matthew-2013/p/4917207.html

再读《被神化的框架》

开发框架,构件,组件非常地多,而且,趋势是越来越多,特别是在java中。当然也不是说其它平台的少。而特别是框架越来越被神化了,似乎用之解决一切问题,不用就要敲坏键盘。对于老衲这样的打字员来说…

河南推出近万亿PPP投资计划 郑州实现智慧城市全覆盖

1 近万亿PPP项目启动 眼下,国内财经新闻的热点聚焦在PPP开发上,这与PPP支撑国内经济平衡运行的一支强劲力量正被政府看好。就连二级市场也出现了PPP概念的抢筹现象。 9月27日,股市再一次遭遇抛售,大盘创出阶段性新低,然…