C++的内部连接和外部连接
转自 :https://blog.youkuaiyun.com/xiexievv/article/details/8491494
当一个实现文件(.cpp …)编译时,预处理器(CPP)首先递归的包含头文件,形成一个保含有所有必要信息的单个源文件. 这个源文件称为 编译单元(translation unit).
内部连接 如果一个名称对于它的编译单元来说是局部的, 并且在连接的时候不可能与其它编译单元中的同样的名称相冲突,则这个名称具有内部连接.即具有内部连接的名称不会被带到目标文件中.
外部连接 在一个多文件程序中,如果一个名称在连接时可以和其他编译单元交互,那么这个名称就具有外部连接. 即具有外部连接的名称会引入到目标文件中,由连接程序进行处理.这种符号在整个程序中必须是惟一的.
具有内部连接的定义包括:
- 加 static 前缀的全局变量定义.如: static int x;
- 枚举类型的定义.如: enum Boolean {NO,YES };
- 类的定义. 如: class Point { int d_x; int d_y; … };
- 内联函数的定义.如: inline int operator==(const Point& left,const Point&right) { … }
- union的定义.
- 名字空间中const常量定义
具有外部连接的定义包括:
- 非内联的类成员函数.如: Point& Point::operator+=(const Point& right) { … }
- 非内联,非静态的自由函数. 如: Point operator+(const Point& left, const Point& right) { … }
- 非静态的全局定义.
声明的内部连接和外部连接
声明本身不会将任何符合引入目标文件,所以声明都是内部连接的.
某些声明可以激活对一个外部连接定义的访问,也许我们会很随便的说这些声明具有外部连接,如:
int f();
extern int i;
class Point { static int s_numPoints; ... }; /* 类静态数据成员声明具有外部连接, 该数据必须在另一个地方被定义,如: point.c文件的int Point::s_numPoints; */
还有一些声明即不把什么符号引入目标文件,也不能用来激活对外部连接定义的访问,我们常常称这类声明具有内部连接,
typedef int INT;
class Point;
struct Point;
把一个带有外部连接的定义放在 .h 文件中都会引起错误.由于类的声明和定义都是内部连接的,一般都放在 .h 文件中.
另外,在C中,const变量是外部连接,C++中,const变量是内部连接
我的理解
- 内部连接可以在多个.cpp中定义,互不影响
- 外部连接不能在多个.cpp中定义,报编译错误
- 有的内部连接可以用extern在其他源文件中访问,有的不能
static void foo() // 不能
constexpr int goo() // 可以 extern constexpr int goo();
inline int soo() // 不能
- 外部连接的定义,定义在cpp文件,extern的声明在h文件,这样可以方便其它文件include。
例如:
int c = 0; // c.cpp文件
extern int c; // c.h 文件
#include "c.h" // 其它用到c的文件
C++内部连接定义
static int a = 1; // static变量
const int b = 1; // 常量
enum Coolean {NO, YES}; // 枚举定义
static void foo() // static 函数
{
}
inline void goo() {} // inline函数
constexpr int soo() {return 1;} // constexpr函数本身就是inline的
class Point //类的定义
{
public:
Point() {};
~Point() {};
}
inline Point::aInline() {}; //类的内连等满足上述条件的类的成员函数
C++外部连接的定义
int a = 1; // 非static、非const/constexpr 的全局变量
void foo() {} // 非static、非inline、非constexpr的自由函数
void Point::setX() {} // 类的其它函数
C的连接有三种
转自:https://docs.microsoft.com/en-us/cpp/c-language/internal-linkage?view=msvc-170
内部连接
static的全局、局部对象(object)
static的函数
(因此,C的所有const常量是外部连接)
外部连接
文件级别的函数声明,有extern
文件级别的对象(object)声明
无连接
代码块级别声明的标识符,且没有extern。
除了对象和函数之外的标识符