首先,我们可以将所有东西都放在一个.cpp文件内.然后编译器就将这个.cpp编译成.obj,obj是什么东西?就是编译单元了.

  一个程序,可以由一个编译单元组成,也可以有多个编译单元组成. 如果你不想让你的源代码变得很难阅读的话,就请使用多个编译单元吧.(一个函数不能放到两个编译单元里面,但两个以上就可以分别放在一个单元,也就是cpp里面)那么就是一个.cpp对应一个.obj,然后将所有的obj链接起来(通过一个叫链接器的程序),组成一个.exe,也就是程序了.

  如果一个.cpp要用到另一个.cpp定义的函数怎么办? 只需在这个.cpp种写上他的函数声明就可以了.其余工作由链接器帮你完成,你可以随便调用该函数.链接器将所有的obj连接起来,但是如果碰巧有相同的函数或外部变量怎么办?他如何识别?一般来说是不能允许在同一个程序中,出现两个一样的函数名或外部变量名.但是只得庆幸的是,c++可以通过一种叫做链接属性的关键字来限定,你这个函数是属于整个程序公用的,还是只是在一个编译单元obj里面使用的.这些关键字就是extern 和 static; extern是外部链接的意思,也就是除了这个单元,外部的单元也是能够访问这个函数的.static 是内部链接,自属于自己单元.说了这么久,还没有说.h的作用呢?其实没有.h也能很好的工作,但是当你发现一个外部链接的函数或外部变量,需要许多份声明,因为c++这种语言,在使用函数和变量的时候,必须将他声明,为何要声明?声明之后才知道他的规格,才能更好的发现不和规格的部分.你别妄想一个编译单元,会自动从另一个编译单元那里得到什么信息,知道你是如何定义这个函数的.所以说,只要使用到该函数的单元,就必须写一份声明在那个.cpp里面,这样是不是很麻烦,而且,如果要修改,就必须一个一个修改.这真让人受不了..h就是为了解决这个问题而诞生,他包含了这些公共的东西.然后所有需要使用该函数的.cpp,只需要用#include包含进去便可.以后需要修改,也只是修改一份内容.请注意不要滥用.h,.h里面不要写代码,.h不是.cpp的仓库,什么都塞到里面.如果在里面写代码,当其他.cpp包含他的时候,就会出现重复定义的情况,比如将函数func(){printf};放到头文件a.h,里面还有一些a.cpp需要的声明等;然后你发现b.cpp需要用到a.cpp里面的一个函数,就很高兴的将a.h包含进来.注意,#include并不是什么申请指令,他就是将指定的文件的内容,原封不动的拷贝进来.这时候实际上a.cpp和b.cpp都有一个func()函数的定义.如果这个函数是内部链接static的话,还好,浪费了一倍空间;如果是extern,外部链接(这个是默认情况),那么根据在同一个程序内不可出现同名函数的要求,连接器会毫不留情给你一个连接错误!;如果你还不太理解.那么就尝试不用h,只用多个cpp看看应该如何写.尝试在两个cpp中写同名函数.看看是否链接出错.尝试在cpp使用其他cpp定义的函数.看看应该如何做.

头文件是没有编译意义的,一般只是编译.cpp生成.obj.但是.cpp里面有#include将指定头文件(其实任何文件都行)插进来,组成完整的.cpp.如果你不喜欢这个方式,你也可以直接在.cpp里面写好了,而不放到.h里面,载用指令拷贝进来.头文件是工具,但不是必须.

个人认为:
     .cpp内用于(1)函数实现(包括全局函数(默认)、静态函数)。

(2)全局变量、静态变量定义。

(3)静态函数声明,静态变量声明。(指定编译单元内部使用的函数和变量)

.h内用于  (1)全局函数声明,注意静态函数不包括在内。

(2)全局变量声明,无静态变量。

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

我的一点总结 by ordedere

上文说到,#include并不是什么申请指令,他就是将指定的文件的内容,原封不动的拷贝进来。所以我们可以将.h的代码连接到.cpp的前端,从而可以更加清晰的看到:

a.h, b.cpp & c.cpp 都同时include了a.h,那么b.cpp其实可以看做是文件:a.h+b.cpp连接而成的cpp源码;而a.h+c.cpp连接成的源码等价于c.cpp include a.h。

那么对于变量在.h中的声明,对cpp有如下情况的分类:

在.h中声明变量int a,等价于在.cpp的前端声明(或者定义)变量全局变量int a;

在.h中声明外部变量extern int a; 等价于在.cpp 的前端声明了外部变量a;所以这个变量a被指明在其他cpp文件中定义;

在.h中声明全局变量 static int a; 等价于在所有包含.h的cpp中将有文件内部的变量a,且每个include该h文件的cpp中的a变量的地址是不同的,也就是原作者说道的空间浪费问题。

同理,对于函数的声明:

在.h 中声明静态(static)函数,就相当于在所包含该头文件的cpp程序中需要定义该静态函数;

在.h中声明外部(extern)函数,即指明该函数的定义是在其他源文件中。

在.h中声明普通函数,即在cpp的开始部分声明一个函数是一个道理。

所以:静态函数和全局静态变量的声明应该在cpp中(毕竟静态的意义就是确保该函数或者变量的作用空间仅限于该源文件内部),而避免在.h中有静态变量或函数的声明。

c++ *.h和*.cpp在编译中的作用的更多相关文章

  1. C++编译与链接(0)-.h与.cpp中的定义与声明

    C++中有的东西需要放在可以在.h文件中定义,有的东西则必须放在.cpp文件中定义,有的东西在不同的cpp文件中的名字可以一样,而有的则不能一样 那么究竟哪些东西可在头文件中定义,声明,哪些东西又必须 ...

  2. 解决Visual C++工程中包含 .c 或cpp文件编译时产生的.pch预编译头错误(C1853)的办法

    2014-01-17 23:36 5128人阅读 评论(1) 收藏 举报 分类: 资料集(282) 版权声明:本文为博主原创文章,未经博主允许不得转载. 之前使用网上的一个开源代码,被封装成Windo ...

  3. template 不能分别在.h和.cpp中定义模板

    先上代码: #ifndef SEQLIST_H #define SEQLIST_H #include <iostream> ; template <typename type> ...

  4. Qt Creator 中,如何更改h,cpp,ui的文件并不让ui失效

    这个星期在使用qt,碰到一个很蛋疼的问题:创建对话框的时候,不小心输错了名字.而且是在很迟才发现的.这个时候对话框都已经布局差不多了,为了改名字,碰到更蛋疼的问题,改了名字后就无法使用转到槽的功能了. ...

  5. makefile多目录的.c 格式.cpp混合编译

    # # c.cpp混合编译的makefile模板 # # BIN = test.exe CC = gcc CPP = g++ #这里只加入库头文件路径及库路径 INCS = -I"c:/mi ...

  6. android 源码编译中的错误 解决

    1.编译种错误提示: arm-none-linux-gnueabi-gcc: directory: No such file or directory arm-none-linux-gnueabi-g ...

  7. include .h 以及.cpp的记录

    VC include 路径解析要了解vc中使用#include命令包含头文件所搜寻的路径,必须先了解vc中的几种路径:1. 系统路径 系统路径在vc中是"Tools->Options- ...

  8. makefile编写---.c .cpp 混合编译makefile 模板

    # c.cpp混合编译的makefile模板 # # BIN = client_system BASE_INSTALL_DIR := /opt/arm-2009q1 BUILD_TOOL_DIR := ...

  9. 第三十一篇 -- 理一下.h和.cpp的关系

    今天突然想到一个问题,我们平时写代码会将代码进行分类,写到不同的cpp里,然后要用到那个类里面的函数,就直接include .h文件就好了.然后今天就在想,.h里面都是一些声明,它是怎么链接到.cpp ...

随机推荐

  1. Linux系统编程--文件IO操作

    Linux思想即,Linux系统下一切皆文件. 一.对文件操作的几个函数 1.打开文件open函数 int open(const char *path, int oflags); int open(c ...

  2. c#读取Word模板,利用书签替换内容包括表格

    //生成WORD程序对象和WORD文档对象 Microsoft.Office.Interop.Word.Application appWord = new Microsoft.Office.Inter ...

  3. fiddler note

    一晚上终于找到对的东西,作者很专业,这里作为笔记,想学习好东西还是到作者那里^_^ ---------------------------------------------------------- ...

  4. My roadway of compilers principles.

    龙书学习过程代码记录--Python3.5(毕竟第一遍看书,书里面的例子全用python写的) One 将中缀表达式翻译成后缀表达式↓ class Parser(object): def __init ...

  5. FORM 提示保存

    修改的FORM在编译到测试环境后打开并没有修改什么数据,却提示是否保存,检查->system.form_satus 为"changed": 个人实际解决情况为:在数据块级的触 ...

  6. JS数组定义【收藏】

    最近在学习JS,刚好学到数组,发现章节还蛮多了而且发现了数组的以前好多不知道的东西,顺便整理下: 数组一共有有四种定义的方式 使用构造函数: var a = new Array(); var b = ...

  7. JavaBean-DAO模式

    一.信息系统的开发架构   客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是客户端,简单的来说就是浏览器. 2.显示层:JSP/S ...

  8. Turtlebot入门篇

    0.什么是TurtleBot? 我自己的理解就是:TurtleBot是一款移动机器人,就是主要研究让机器人自主决定应该想那个方向走,怎么绕过障碍物,最终到达目的地.与之对应还有很多机器人,比如goog ...

  9. Android安装失败 Installation error code: -110

    在系统开发过程中,开发的app管理器,发现怎么安装都是失败. 详细的查看了log发现. I/ActivityManager(  899): START {dat=file:///mnt/sdcard/ ...

  10. mysql 乱码问题

    A.mysql设置 1.service mysql stop 2.sudo vim /etc/mysql/my.cnf 在[mysqld]中添加下面两行 character_set_server = ...