C++ 多文件编译简述:头文件、链接性、声明与定义
Commen Sense
C++ 在编译时对每个翻译单元(Translation Unit,通常是文件,下文以文件代称)单独编译。
注意区分 声明(Declaration) 和 定义(Definition):
声明规定了变量的类型和名字;
定义则负责创建与名字关联的实体,定义还申请存储空间。[1]
C++ 的“单定义规则”指出变量只能有一次定义。
注意区分 作用域(Scope) 和 链接性(Linkage):
作用域描述名称在文件的多大范围可见;
链接性描述名称如何在不同单元间共享。
头文件
头文件中常包含的内容
- 函数原型
- 使用
#define或const定义的符号常量- 结构声明
- 类声明
- 模板声明
- 内联函数
普通函数的定义不能放在头文件中,即使使用了 #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++ 多文件编译简述:头文件、链接性、声明与定义的更多相关文章
- gcc编译时头文件和库文件搜索路径
特殊情况:用户自定义的头文件使用#include"mylib"时,gcc编译器会从当前目录查找头文件 一.头文件 gcc 在编译时寻找所需要的头文件 : ※搜寻会从-I开始( ...
- gsoap 学习 1-由wsdl文件生成h头文件
开始前先看一下用户向导吧 http://www.cs.fsu.edu/~engelen/soap.html 中左侧点击Documentation 英语水平确实有限,有些内容可能说的不准确,敬请参考向导 ...
- C/C++头文件以及避免头文件包含造成的重定义方法
C 头文件 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享.有两种类型的头文件:程序员编写的头文件和编译器自带的头文件. 在程序中要使用头文件,需要使用 C 预处 ...
- Swift中不用桥接文件和.h头文件直接和C代码交互的方法
我们知道一般情况下Swit要想调用obj-c,c或c++代码必须通过obj-c以及桥接文件才可以办到,但是对于某些简单的代码,我们可以跳过桥接文件和.h头文件,直接和C代码交互呢! 我们再Projec ...
- C#.NET常见问题(FAQ)-如何将cs文件编译成dll文件 exe文件 如何调用dll文件
比如我要把TestDLL.cs文件编译成dll文件,则在命令提示符下,输入下面的命令,生成的文件为TestDLL.dll csc /target:library TestDLL.cs 注意前提是你安装 ...
- 用gulp把less文件编译成css文件
第一次使用gulp构建工具,使用gulp将.less文件编译成.css文件并输出.根据视频做了笔记.提供新手和自己以后做参考. HTML文件 <!DOCTYPE html> <htm ...
- C#.NET如何将cs文件编译成dll文件 exe文件 如何调用dll文件
比如我要把TestDLL.cs文件编译成dll文件,则在命令提示符下,输入下面的命令,生成的文件为TestDLL.dll csc /target:library TestDLL.cs 注意前提是你安装 ...
- 在JAVA中将class文件编译成jar文件包,运行提示没有主清单属性
在JAVA中将class文件编译成jar文件包,运行提示没有主清单属性 Maven 项目生成jar运行时提示“没有主清单属性” 新建了一个Maven的项目,mvn compile和mvn packag ...
- 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 ...
随机推荐
- MFC界面库BCGControlBar v30.1——Grid/Report控件
亲爱的BCGSoft用户,我们非常高兴地宣布BCGControlBar Professional for MFC和BCGSuite for MFC v30.1正式发布!此版本包含themed find ...
- hiho #1485 : hiho字符串(滑动窗口)
#1485 : hiho字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 如果一个字符串恰好包含2个'h'.1个'i'和1个'o',我们就称这个字符串是hiho字符 ...
- 【LuoguP4081】[USACO17DEC]Standing Out from the Herd
题目链接 题意 给定多个字符串,每个串中仅在该串中出现的本质不同的子串个数. Sol 多串匹配想到用广义SAM. 之后从串的匹配角度不是很好做.发现一个本质不同的串最多只会贡献到一个串的答案里. 那么 ...
- [深度学习] R-CNN系论文略读
总结: 一.R-CNN 摘要: 在对象检测方面,其性能在前几年就达到了一个比较稳定的状态.性能最好的方法是一种复杂的整体系统,它将多个图片的低级特征通过上下文组合起来. 本文提出了一种简单.可扩展的算 ...
- javascript中的原型和原型链(四)
new运算符工作原理
- idea maven projects 工具栏按钮的作用
1.Execute Maven Goal 弹出可执行的 Maven 命令的输入框.有些情况下我们需要通过书写某些执行命令来构建项目,就可以通过此按钮 2.Toggle Offline Mode 英文 ...
- Codeforces Round #201.C-Alice and Bob
C. Alice and Bob time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- SpringMVC的 transferTo使用
在开发Web应用程序时比较常见的功能之一,就是允许用户利用multipart请求将本地文件上传到服务器,而这正是Grails的坚固基石——SpringMVC其中的一个优势.Spring通过对Servl ...
- TensorFlow自动求梯度
例1 import tensorflow as tf a=tf.Variable(tf.constant(1.0),name='a') b=tf.Variable(tf.constant(1.0),n ...
- mysql 查询一个月的数据
//今天 select * from 表名 where to_days(时间字段名) = to_days(now()); //昨天 SELECT * FROM 表名 WHERE TO_DAYS( NO ...