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 ...
随机推荐
- 基于Python原生asyncio模块对DNS正向和反向的解析
一.正向解析:域名解析IP地址 import asyncio import socket domains = [ ('www.baidu.com', 'https'), ('cn.bing.com', ...
- yum provides 反查询
yum provides 可以反查询到 你要使用的命令包含 在哪个包里 然后使用yum install 即可安装: [root@git02 ~]# yum provides */nslookupLo ...
- ASE高级软件工程 第一周博客作业
1.自我介绍 我叫姚顺,是来自哈尔滨工业大学计算机学院的一名大四本科生,专业方向计算机科学,目前在KC组实习.平时的业余时间主要用来打篮球,听音乐,跑步,当然还有游戏(划掉).之前的大学三年主要用来做 ...
- codevs 2597 团伙x
题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的 ...
- Python3学习笔记(十二):闭包
闭包定义: 在一个外函数中定义了一个内函数,内函数里引用了外函数的临时变量,并且外函数的返回值是内函数的引用.这样就构成了一个闭包. 我们先来看一个简单的函数: def outer(a): b = 1 ...
- Golang协程实现流量统计系统(1)
# 学习内容: # 学习目标: 学习Golang的基础开发 常用的Golang编程技艺 精巧省力的Go Lib 协程的真实应用实践 与其他语言对比着学 协程并发模型的深度应用 Growth hacki ...
- bootstrap 学习笔记(部分)
这个课程中的boostrap是3.0+版本的.(2.0与3.0有区别) bootstrap中的JS是依赖于jquery的,所以需要事先引用jquery(1.9.0版本以上). <!DOCTYPE ...
- 【Spark机器学习速成宝典】模型篇08保序回归【Isotonic Regression】(Python版)
目录 保序回归原理 保序回归代码(Spark Python) 保序回归原理 待续... 返回目录 保序回归代码(Spark Python) 代码里数据:https://pan.baidu.com/s/ ...
- 查询一个redis集群的大keys 脚本
1. 把redis集群中的 master 节点信息记录在文件 redis_object_port.info 中, 方便下一步遍历各实例中的大 keys redis-cli -h 10.240.47.1 ...
- 从curl命令获取libcurl的用法
libcurl的用法参数太多 有时候弄不好 可以先用curl命令实现了 然后获取相应的libcurl代码 比如要上传文件 curl -T d:/h.txt http://demo.xudp.cn/up ...