在上一篇文章中,我们知道:可以通过声明 const/ static 变量来隔离变量在源文件的可见性,来解决变量重复定义的问题,
C++:重定义:符号重定义:变量重定义(二):解决变量重定义(const static)_hongwen_yul的博客-CSDN博客
这一篇文章我们介绍:如果都不 include 这个头文件(就是说我源文件都不包含变量 A ),那也解决了重定义的问题了。为此C++ 提出了 “extern” 这个关键字来解决这个问题。
extern :
- extern是一个关键字,它告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面中没有找到相应的变量或者函数, 也会在当前文件的后面或者其它文件中定义.
- extern还要一个好处就是:我就是想用某个头文件某个变量,但是这个头文件有太多逻辑,我又不想把一些无关代码逻辑 include进来,那么将你想使用的这个变量声明为 extern外部变量,是一个很好的方法。
1:extern变量理论依据
- 外部变量(即全局变量)函数外部定义的变量,它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。
- 外部变量实在函数外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。
- 如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字 extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。
- 关于extern关键字,谭浩强老师的<<C语言程序设计>>中有一段精准而到位的表述:
2:用 extern 声明外部变量,扩展程序文件中的作用域。
#include<iostream>
int max(int x, int y)
{
int z;
z = x > y ? x : y;
return(z);
}
int main()
{
extern int C, B;
printf("%d\n", max(C, B));
return 0;
}
int C = 13, B = -8;
// 很显然:在mian()函数:printf() 函数:max()函数需要用到 变量 C 和 B
// 但是 这两个变量是在使用之后定义的
// 为了能这样使用,我们将变量 用 extern修饰
// 这样声明了 两个外部变量 extern int C, B ,扩展了变量的作用域(并且作用域从变量声明开始到 源文件结束)
采用 gcc 命令输出结果
1: gcc -mian.cpp -o mian.exe : 输出 应用程序 main.exe
2: ./main.exe : 运行当前程序
3:13 : 程序运行结果
PS : 如果在编译过程中,gcc 指令出现下面错误:
undefined reference to `std::ios_base::Init::Init() 解决
(一)gcc 编译C++程序是提示错误undefined reference to `std::ios_base::Init::Init() 的解决方法
在linux下编译c++ 程序要使用g++ 编译器,如果你要是使用gcc编译器就会有上面的报错信息,只要在在gcc后加上 -lstdc++就ok了
eg: gcc example.c -lstdc++
(二)gcc 和 g++ 是有区别的
(1)gcc和g++都是GNU(组织)的一个编译器。
(2)后缀名为.c的程序和.cpp的程序g++都会当成是c++的源程序来处理。而gcc不然,gcc会把.c的程序处理成c程序。
(3)对于.cpp的程序,编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。(个人觉得这条是最重要的)
3:用 extern 声明外部变量,其他源文件定义变量
公共头文件
a.h
#pragma once
extern int A;
//很多其他代码。。。。。。
a.cpp
#include"a.h"
int A = 3;
=========================================================================================
b.h
#pragma once
#include<string>
void fb();
b.cpp
#include"b.h"
extern int A;
void fb() {
printf("%d", A+1);
}
===========================================================================================
c.h
#pragma once
#include<string>
void fc();
c.cpp
#include"c.h"
extern int A;
void fc() {
printf("%d", A + 2);
}
======================================================================================
main.cpp
#include<string>
#include"b.h"
#include"c.h"
#include<iostream>
int main() {
fb();
std::cout << "\n" << std::endl;
fc();
return 0;
}
// b.cpp 和 c.cpp 这两个源文件最大的区别就是:他们的头文件 b.h / c.h 并没有 include"a.h"
这样在 main.cpp 调用 b.cpp / c.cpp 函数做链接时,不会出现 变量A 重复定义的情况。
// 那么 main.cpp文件中 有想使用 变量 A ,就只能 通过 extern 来声明了
// 当编译器遇到 extern 时,就会知道,这个变量是一个外部变量,我应该在 本文件末尾或者其他文件寻找这个变量的定义。
打印结果 :4 5