外部链接和变量前向声明
本节阅读量:在上一课中,我们讨论了内部链接如何将标识符的使用限制在单个文件。在本课中,我们将探索外部链接的概念。
具有外部链接的标识符既可以从定义它的文件中看到,也可以从其他代码文件中使用(通过前向声明)。在这种意义上,具有外部链接的标识符是真正的“全局”标识符,因为它们可以在程序中的任何位置使用!
默认情况下,函数具有外部链接
在前面多个代码文件的程序中,可以从一个文件调用在另一个文件中定义的函数。这是因为函数在默认情况下具有外部链接。
为了调用在另一个文件中定义的函数,必须在使用该函数的任何其他文件中放置该函数的前向声明。前向声明将函数的存在告知编译器,链接器将函数调用连接到实际的函数定义。
下面是一个示例:
a.cpp:
|
|
main.cpp:
|
|
上述程序打印:
|
|
在上面的示例中,main.cpp中函数 sayHi() 的前向声明,允许main.cpp访问在a.cpp.中定义的 sayHi() 函数。前向声明满足了编译器的要求,并且链接器能够将函数调用链接到函数定义。
如果函数 sayHi() 具有内部链接,则链接器将无法将函数调用连接到函数定义,并将导致链接错误。
具有外部链接的全局变量
具有外部链接的全局变量有时称为外部变量。要将全局变量设置为外部变量(因此可由其他文件访问),可以使用extern关键字执行此操作:
|
|
默认情况下,非常量的全局变量是外部链接(添加extern关键字也会被忽略)。
通过extern关键字进行变量前向声明
要实际使用在另一个文件中定义的外部全局变量,还必须在希望使用该变量的任何其他文件中放置全局变量的前向声明。对于变量,也可以通过extern关键字(没有初始化值)创建前向声明。
下面是使用变量前向声明的示例:
a.cpp:
|
|
main.cpp:
|
|
在上面的示例中,a.cpp和main.cpp都引用了名为g_x的相同全局变量。因此,即使g_x是在a.cpp中定义和初始化的,我们也可以通过g_x的前向声明在main.cpp内使用它的值。
请注意,extern关键字在不同的上下文中具有不同的含义。在某些上下文中,extern意味着“为该变量提供外部链接”。在其他上下文中,extern意味着“这是在其他地方定义的外部变量的前向声明”。是的,这很令人困惑,因此我们在后续课程中总结了所有这些用法——作用域、存储期和链接。
注意,函数前向声明不需要extern关键字——编译器能够根据是否提供函数体来判断您是在定义新函数还是在进行前向声明。变量前向声明确实需要extern关键字来帮助区分未初始化的变量定义和变量前向声明(它们在其他方面看起来相同):
|
|
警告
如果要定义未初始化的非常量全局变量,请不要使用extern关键字,否则C++会认为您正在尝试对该变量进行前向声明。
警告
尽管可以通过extern关键字为constexpr变量提供外部链接,但它们不能前向声明为constexpr。这是因为编译器需要知道constexpr变量的值(在编译时)。如果该值在其他文件中定义,则编译器对该其他文件中所定义的值不可见。
然而,您可以将constexpr变量前向声明为const,编译器将其视为运行时常量。这并不是特别有用。
快速摘要
|
|
