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 ...
随机推荐
- IPC 进程间通信方式——管道
进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...
- .net中[Serializable]序列化的应用
原文链接:https://blog.csdn.net/wanlong360599336/article/details/9222459 浅析.NET中的Serialization 摘要 本文简要介绍了 ...
- Here is a test page for my new blog in cnblogs
Tell me if I can use Fomula like LaTeX $$\sum\limits_{i = 1}^{n}a_i$$
- Java中SSM+Shiro系统登录验证码的实现方法
1.验证码生成类: import java.util.Random; import java.awt.image.BufferedImage; import java.awt.Graphics; im ...
- linux中more命令如何使用
more命令,功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上.兄弟连Linux培训教程() more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(sp ...
- 排序(sort)
1.定义 排序 所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.其确切定义如下: 输入:n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn. 输出:Ril ...
- HGOI20190809 省常中互测2
Problem A 时之终结 构造一个含有$n$个节点的无重边无自环的有向图, 使得从$1$出发,每一次经过一条$(u,v) (u < v)$的边到达节点$n$的方案恰好有$y$种. 对于$10 ...
- centos 6.8安装mysql5.6
安装mysql 官方文档 A Quick Guide to Using the MySQL Yum Repository 下载 Yum Repository Go to the Download My ...
- Spring Boot教程(二十九)使用JdbcTemplate操作数据库
使用JdbcTemplate操作数据库 Spring的JdbcTemplate是自动配置的,你可以直接使用@Autowired来注入到你自己的bean中来使用. 举例:我们在创建User表,包含属性n ...
- bootstrap editable有默认值
function listEditor(data,productCode) { $('#tab1').bootstrapTable('load', data); $('#tab1').bootstra ...