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 ...
随机推荐
- c3p0连接池:com.mysql.cj.exceptions.InvalidConnectionAttributeException
1 遇到的错误com.mysql.cj.exceptions.InvalidConnectionAttributeException: 四月 17, 2019 10:21:13 上午 com.mcha ...
- php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--服务端
绑定tcp服务器的地址 $swserver = new swoole_server("127.0.0.1",9501); 设置tcp服务器装机容量(太危言耸听了-其实就是设置属性) ...
- IPC 进程间通信方式——管道
进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...
- 解决c#distinct不好用的问题
当一个结合中想根据某一个字段做去重方法时使用以下代码 IQueryable 继承自IEnumerable 先举例: #region linq to object List<People> ...
- java设置Cookie
public static void setCookie(HttpServletResponse response, String key, String value){ Cookie cookie ...
- rgb三基色与rgba
主要解释什么是三基色和RGBA ㈠三基色含义 三基色是指红,绿,蓝三色,人眼对红.绿.蓝最为敏感,大多数的颜色可以通过红.绿.蓝三色按照不同的比例合成产生. ㈡三基色原理 ⑴自然界中的绝大部分彩色,都 ...
- maven项目创建4
运行maven项目,首先要不最根项目添加到maven本地仓库,执行 项目-->右键-->Run as-->Maven install 注:创建war包项目,本地测试,创建index ...
- 【BZOJ3261】最大异或和(可持久化Trie)
题意: 思路:可持久化Trie板子题,支持序列插入和询问 #include<bits/stdc++.h> using namespace std; typedef long long ll ...
- Mybatis 结果映射下划线转驼峰
mybatis 结果映射下划线转驼峰 Spring Boot 配置: #下划线转驼峰 mybatis.configuration.map-underscore-to-camel-case=true m ...
- Linux命令-文件管理(二)
Linux命令-文件管理(二) Linux gitview命令 Linux gitview命令用于观看文件的内容,它会同时显示十六进制和ASCII格式的字码. 语法:gitview [-bchilv] ...