内部链接
本节阅读量:在局部变量一节中,我们说过,“标识符的链接属性决定了该名称的其他声明是否引用同一对象”,同时也得知–局部变量没有链接属性。
全局变量和函数标识符可以具有内部链接或外部链接属性。我们将在本课中介绍内部链接的情况,在下一节中介绍外部链接。
具有内部链接的标识符可以在单个翻译单元内看到并使用,但它不能从其他翻译单元访问(即,它不向链接器公开)。这意味着,如果两个源文件具有具有内部链接的同名标识符,则这些标识符将被视为独立的(并且不会因具有重复定义而导致ODR冲突)。
具有内部链接的全局变量
具有内部链接的全局变量有时称为内部变量。
为了使非常量的全局变量成为内部变量,使用static关键字。
|
|
默认情况下,Const和constexpr全局变量具有内部链接属性(因此不需要static关键字——如果使用static关键字也无额外作用)。
下面是使用内部变量的多个文件的示例:
a.cpp:
|
|
main.cpp:
|
|
该程序打印:
|
|
因为g_x是每个文件的内部变量,所以main.cpp不知道a.cpp也有一个名为g_x的变量(反之亦然)。
对于高级读者
上面static关键字的使用是存储类说明符( storage class specifier)的一个示例,它设置名称的链接属性及其存储期。最常用的存储类说明符是static、extern和mutable的。
具有内部链接的函数
由于链接是标识符的属性(不是变量的属性),函数标识符也具有链接属性。函数默认为外部链接(我们将在下一课中介绍),但可以通过static关键字设置为内部链接:
add.cpp:
|
|
main.cpp:
|
|
此程序无法链接成功,因为在add.cpp之外无法访问函数add。
单定义规则和内部链接
根据单定义规则,我们注意到,对象或函数不能在文件或程序中具有多个定义。
然而,值得注意的是,在不同文件中定义的内部对象(和函数)被认为是独立的实体(即使它们的名称和类型相同),因此不会违反单定义规则。每个文件内部对象只有一个定义。
static 对比 未命名的命名空间
在现代C++中,使用static关键字为标识符提供内部链接越来越不受欢迎。未命名的名称空间可以为更广泛的标识符(例如,类型标识符)提供内部链接,并且它们更适合为多个标识符提供内部链接。
在后续,会讨论未命名的名称空间。
为什么要费心为标识符提供内部链接?
让标识符具有内部链接通常有两个原因:
- 有一个标识符,我们要确保其他文件无法访问。这可能是一个我们不想弄乱的全局变量,或者是一个不想调用的辅助函数。
- 避免命名冲突。由于具有内部链接的标识符不会向链接器公开,因此它们只能与同一翻译单元中的名称发生冲突,而不会在整个程序中发生冲突。
许多现代开发指南建议,不打算在其它文件中访问的变量或函数,都设置为内部链接。如果你可以完全遵守,这是一个很好的建议。
当然,有一个更为轻量级的准则:将有明确理由不允许从其他文件访问的任何标识符设置为内部链接。
最佳实践
当您有明确的理由不允许从其他文件访问时,将标识符设置为内部链接。
最好将您不希望其他文件访问的所有标识符设置为内部链接(使用未命名的命名空间)。
快速摘要
|
|
