先 写下 几个 名词 : 预处理, 编译(obj), 链接(exe), 编译单元, 内部链接, 外部链接
( 在 看 之前 要对 c++ 中 的 声明 定义 初始化 左值 右值 掌握 ,很容易混。 网上 很多 名词 用的不恰当或 错误, 本文很可能有 0.0 欢迎指正)
预处理主要负责 : 1.宏的替换
2.删除注释(编译器参数 可以设置)
3.处理预处理指令 (#include, #ifdef), 把头文件中的 声明 加到cpp文件中
编译单元 : 指的是 单个.cpp文件 且 包括 该cpp文件中 包含的头文件(递归包含)
.h文件是不会被编译器单独编译的 [c++ 中的 .hpp文件 简单一提 像是头文件 和 实现文件的结合]
编译器会为每个编译单元进行编译, 生成相应的obj文件
然后链接器将所有obj文件 进行链接, 生成可执行文件。
内部链接,
外部链接 : 这两个 名词 指的都是 代码中的 变量(不只是 “变量”)的属性。
如果 一个名称 对于一个 编译单元来说 是 局部的,且 在链接的时候不可能与
其他的编译单元中的 同名 变量 冲突, 则 这个变量就是具有 内部链接的。
外部链接 相对 内部链接, 就是变量 能被引入 目标文件(.obj)中,对其他编译单元
可见。 对其的 要求是 名字唯一。
然后说下 各种标识符 会给 变量带来什么 影响 :
举个例子 : static int x,
enum Bollean {eFalse, eTrue};
class T {}; inline int operator==(const Point& _left,
const Point& _right);
以上都是 具有 内部链接属性的 ;再来看下 外部链接
外部链接: 非内联的类成员函数 Point& Point::operator+=(Point const& right) {}
非内联, 非静态的自由函数 Point operator+=(Point const& left, Point const& right){}
非静态的 全局定义
上面大体说了下 有个 感性认识 然后 在 继续 细说:
extern: 他是 声明符 意在 表明 这只是个声明 告诉你 有这么个东西 到别处(其他编译单元等)找。
extern把其修饰的变量 凡在 为解决符号表(这个表 也忘说了.. 一共 2 个 还是 3 个,还有个 虚函数表vtb)里。
static : 说过了,但凡是 被 修饰的 都是 内部链接 不 导出 。
const : 默认 内部链接, 可通过 加 extern 和 static 来改变
extern const int a = 35;
为什么头文件里一般只可以有声明不能有定义:
头文件可以被多个编译单元包含,如果头文件里有定义,那么每个包含这个头文件的编译单元就都
会对同一个符号进行定义,如果该符号为外部链接,则会导致duplicated external simbols。因
此如果头文件里要定义,必须保证定义的符号只能具有内部链接。
为什么常量默认为内部链接,而变量不是:
这就是为了能够在头文件里如const int n = 0这样的定义常量。由于常量是只读的,因此即
使每个编译单元都拥有一份定义也没有关系。如果一个定义于头文件里的变量拥有内部链接,
那么如果出现多个编译单元都定义该变量,则其中一个编译单元对该变量进行修改,不影响
其他单元的同一变量,会产生意想不到的后果。【网上看到的 . 没看懂这句 解释
个人理解 头文件中的 都必须是内部链接(我意思是 变量都应该是) 求 解答】
To be continue ...