extern 作用
一、变量的外部链接
🍀引例
提问:在一个项目中,多个源文件定义同一个变量会发生什么?
//test1.cpp
int a = 10;
namespace name {
int b = 10;
int c = 10;
}
//test2.cpp
int a;
int b = 20;
namespace name {
int c = 20;
}
int main() {
cout << name::b; //error,只能使用变量 c
return 0;
}
🍀上面代码结果
- 对于变量 a,因为两个源文件都定义了全局变量 a ,所以会导致链接错误。这是因为 C++ 的链接规则要求每个全局变量在整个程序中只能有一个定义
- 对于变量 b 和 c,因为其中一个变量定义在命名空间 name 中,所以不会发生错误
- 对于命名空间 name,不同源文件定义相同的命名空间不会发生错误,因为每个命名空间的作用域是该源文件
🍀解决方法—— extern
extern 关键字用于声明变量的外部链接性,它告诉编译器该变量在其他文件中定义
//方法1:在头文件中使用 extern
//test1.cpp
int a = 10;
//test.h
#pragma once
#include <iostream>
using namespace std;
extern int a;
//test2.cpp
#include "test.h"
int main() {
cout << a; //10
a = 20; //改变全局变量的值
return 0;
}
//方法2:直接在源文件中声明
//test1.cpp
int a = 10;
//test2.cpp
#include <iostream>
extern int a;
int main() {
std::cout << a; //10
a = 20; //改变全局变量的值
return 0;
}
❗️注意:extern 不能声明命名空间
//test1.cpp
namespace name {
int a = 10;
int b = 20;
}
//test2.cpp
extern namespace name; //error,因为 namespace 并不能作为变量类型
二、函数的外部链接
- 函数默认具有外部链接性。也就是说,即使不使用 extern,你也可以在其他文件中调用函数(只需要先声明一下)
//test1.cpp
void fun() {
int a = 10;
}
//test2.cpp
void fun(); //声明
int main() {
fun();
return 0;
} //运行正确
- 因为函数具有默认属性,所以我们不能重复定义函数(重载可以),否则会链接错误
//test1.cpp
void fun() {
int a = 10;
}
//test.cpp
void fun() { //error,重复定义
int b = 10;
}
void fun(int a) { //不会报错,函数重载
int b = a;
}
- 使用 extern 声明函数通常是为了在头文件中声明函数接口
//test1.cpp
void fun() {
int a = 10;
}
//test.h
extern void fun();
//test2.cpp
#include "test.h"
int main() {
fun();
return 0;
}
三、extern 和作用域
🍀extern 关键字声明的变量或函数可以在整个程序中访问,但它的定义必须存在于其他地方。这有助于在多个源文件之间共享变量和函数
常见用法
- 头文件中的声明:extern 常用于头文件中,用于声明全局变量或函数,以便其他源文件能够引用这些变量或函数
- 分离声明和定义:通过在头文件中使用 extern 声明变量或函数,可以将定义和使用分离,使得代码组织更加清晰
本篇文章到此就结束啦,欢迎批评指正!