Commen Sense

C++ 在编译时对每个翻译单元(Translation Unit,通常是文件,下文以文件代称)单独编译。

注意区分 声明(Declaration)定义(Definition)

声明规定了变量的类型和名字;
定义则负责创建与名字关联的实体,定义还申请存储空间。[1]

C++ 的“单定义规则”指出变量只能有一次定义。

注意区分 作用域(Scope)链接性(Linkage)

作用域描述名称在文件的多大范围可见;
链接性描述名称如何在不同单元间共享。

头文件

头文件中常包含的内容

  • 函数原型
  • 使用 #defineconst 定义的符号常量
  • 结构声明
  • 类声明
  • 模板声明
  • 内联函数

普通函数的定义不能放在头文件中,即使使用了 #ifndef 等预处理指令防止头文件被重复包含。这是因为每个源文件被单独编译,头文件中的函数定义会使链接后的程序包含多个重复定义,预处理指令只能保证单个文件被单独编译时不会出现头文件的重复展开。

内联函数需要在每一个调用点都对编译器可见,因此通常直接放在头文件中被所有实现文件 include。

模板函数和模板类的定义不会产生任何“实体”函数,因此可以出现在头文件中。又由于与内联函数类似的原因,其通常都被放在头文件中。

类的声明和实现通常分处于一个头文件(.h)和实现文件(.cpp)中,由于模板类的特性,可将声明与实现合并到一个文件(.hpp)简化源文件结构。但非模板类的实现显然不能位于头文件中。

链接性

以下关键字都可能有多义,这里仅讨论与链接性有关的功能。本节涉及的变量皆指 C++ 内存模型中的静态持续变量。

链接性分为三种:外部链接性、内部链接性、无链接性,含义见下文。

static 与链接性控制

在代码块的外部使用 static 声明变量和函数使其具有内部链接性,在当前文件外不可见。

在代码块的内部使用 static 声明变量和函数使其无链接性,只能在当前函数或代码块中访问。

在代码块的外部不使用 static 声明变量和函数使其具有外部链接性,可在其他文件中访问。

extern 与外部链接性

extern 用于声明一个变量(而非定义它)。因此,在头文件中包含变量的声明可以使得其在所有包含该头文件的源文件中都可见,即实现一种“全局变量”的效果。但须保证有且仅有一次变量的定义。

例如,在头文件 header.h 中加入声明语句 extern int ver;,并在源文件 a.cpp 中加入定义 int ver; ,则所有包含 header.h 的源文件都可以直接使用变量 ver。而若 a.cpp 中的定义语句为 static int ver; ,则变量 ver 失去外部链接性,若有其他源文件引用它,即使包含了 header.h 也会导致链接出错。

但形似 extern int x = 1; 的语句声明并定义变量。

Reference

[0] 本文中的引文内容如无特殊标注皆引自《C++ Primer Plus

[1] C++中extern关键字用法小结, Broglie @ cnblogs

C++ 多文件编译简述:头文件、链接性、声明与定义的更多相关文章

  1. gcc编译时头文件和库文件搜索路径

    特殊情况:用户自定义的头文件使用#include"mylib"时,gcc编译器会从当前目录查找头文件 一.头文件 gcc 在编译时寻找所需要的头文件 :    ※搜寻会从-I开始( ...

  2. gsoap 学习 1-由wsdl文件生成h头文件

    开始前先看一下用户向导吧 http://www.cs.fsu.edu/~engelen/soap.html 中左侧点击Documentation 英语水平确实有限,有些内容可能说的不准确,敬请参考向导 ...

  3. C/C++头文件以及避免头文件包含造成的重定义方法

    C 头文件 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享.有两种类型的头文件:程序员编写的头文件和编译器自带的头文件. 在程序中要使用头文件,需要使用 C 预处 ...

  4. Swift中不用桥接文件和.h头文件直接和C代码交互的方法

    我们知道一般情况下Swit要想调用obj-c,c或c++代码必须通过obj-c以及桥接文件才可以办到,但是对于某些简单的代码,我们可以跳过桥接文件和.h头文件,直接和C代码交互呢! 我们再Projec ...

  5. C#.NET常见问题(FAQ)-如何将cs文件编译成dll文件 exe文件 如何调用dll文件

    比如我要把TestDLL.cs文件编译成dll文件,则在命令提示符下,输入下面的命令,生成的文件为TestDLL.dll csc /target:library TestDLL.cs 注意前提是你安装 ...

  6. 用gulp把less文件编译成css文件

    第一次使用gulp构建工具,使用gulp将.less文件编译成.css文件并输出.根据视频做了笔记.提供新手和自己以后做参考. HTML文件 <!DOCTYPE html> <htm ...

  7. C#.NET如何将cs文件编译成dll文件 exe文件 如何调用dll文件

    比如我要把TestDLL.cs文件编译成dll文件,则在命令提示符下,输入下面的命令,生成的文件为TestDLL.dll csc /target:library TestDLL.cs 注意前提是你安装 ...

  8. 在JAVA中将class文件编译成jar文件包,运行提示没有主清单属性

    在JAVA中将class文件编译成jar文件包,运行提示没有主清单属性 Maven 项目生成jar运行时提示“没有主清单属性” 新建了一个Maven的项目,mvn compile和mvn packag ...

  9. ubuntu64位系统编译时头文件找不到的问题(可以查看g++ -v路径,设置export C_INCLUDE_PATH,CPLUS_INCLUDE_PATH)

    今天编译webrtc时出现以下错误: ninja -C out/Debug Allninja: Entering directory `out/Debug'[1/6] CXX obj/talk/app ...

随机推荐

  1. Android 腾讯bugly Tinker 热修复

    Bugly热更新是腾讯推出的热更新框架,热更新是指无需到应用市场重新下载安装app,只需要在app内下载补丁包即可实现app的更新,主要用于app的bug修复或者少量改动. 大家在使用app(特别是游 ...

  2. JavaScript 的定时(Timing )事件——setTimeout()与setInterval()

    JavaScript 可以在时间间隔内执行,这就是所谓的定时事件( Timing Events). ㈠Timing 事件 ⑴window 对象允许以指定的时间间隔执行代码,这些时间间隔称为定时事件. ...

  3. HTML中的表格和图像总结

    ㈠表格 ⑴表格的基本结构 ①表格的基本标签有:table标签(表格),tr标签(行),td标签(单元格).<tr>标签和<td>标签都要在表格的开始标签<table> ...

  4. C# 动态访问webserver 帮助类

    /* 调用方式 * string url = "http://www.webservicex.net/globalweather.asmx" ; * string[] args = ...

  5. mongodb性能测试:long时间戳与string格式时间

    string格式时间写入数据: { "_id" : ObjectId("5d314731a96f332d6c3193d4"), "news_id&qu ...

  6. K8S容器探针

    容器探针 探针是由 kubelet对容器执行的定期诊断.要执行诊断, kubelet 调用由容器实现的    Handler .有三种类型的处理程序:   ExecAction :在容器内执行指定命令 ...

  7. R & and &&

    https://blog.csdn.net/jining11/article/details/84933110 和C中的&不用,不要用&&,一般情况都是用&表示并且

  8. C语言博客作业04数组

    0.展示PTA总分 1.本章学习总结 1.1 学习内容总结 1.int a[10];为定义数组,表示数组有10个数 2.数组的下标都是从0开始,到n-1结束 3.数组里元素的个数不能大于数组的长度 4 ...

  9. PyQT5堆叠布局:切换界面(QStackedLayout)

    几乎所有的GUI界面都需要用到这个场景:在一个界面里面,点击不同的按钮显示不同的内容 在Qt设计师中没有堆叠布局,需要我们手动添加 在Qt设计师中,设计3个切换的页面,和一个主界面. 注意在主界面是两 ...

  10. CodeForces 788B--Weird journey

    Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Description Little ...