-
extern关键字
- 一般用法:由于在C++中全局变量可以被定义在函数外面的任何地方。当我们想在某行使用全局变量时,如果当前文件的该行前找不到该全局变量的定义,那就必须在前面使用extern声明这个变量才可以使用该全局变量(extern声明只针对全局变量,不能使用在局部变量)。
- 举例:
extern int a; extern int b; int maxbb(int l,int r) { return l > r ? l : r; } int main() { cout << maxbb(a, b) << endl; } int a = 10; int b = 20;
-
理解:就如同我们使用某个前面没有定义的函数一样,只有前面声明了该函数,编译器才知道该如何执行。用exter声明全局变量其实同理,就是让编译器知道这个是全局变量,以及它的类型。
-
补充:
- 像函数声明一样,我们也经常用extern声明全局变量,并将它们放到.h头文件中(我们知道一个.cpp文件include一个头文件,在编译时会把include这一句源封不动的直接替换成头文件中的内容)。这样就可以在不同的文件中定义或者使用这个全局变量了(看上面这个例子,是放在.cpp文件中的,这样的话所有使用这个全局变量的文件都要写一遍extern int a;extern int b;这两句声明,相当麻烦,这些都是和函数声明一样的道理)。
- extern还有一个不太被关注的作用是,它可以改变const变量的链接属性。
-
链接属性
- C/C++代码的编译通常经过预编译,汇编,编译,链接。通常变量会有三种链接属性:外部链接,内部链接或无链接。具有函数作用域,块作用域或者函数原型作用域的变量都是无链接变量;具有文件作用域的变量可以是内部链接也可以是外部链接。而外部链接变量可以在多个文件中使用,内部链接变量只能在一个编译单元中使用(一个源代码文件和它包含的头文件)。
- 简单的来说,只要不是文件作用域的变量,基本是无链接属性。而用const修饰的全局变量或者static修饰的变量拥有内部链接属性,它们只在当前文件中有效,对其他文件来说是不可见的。其他一般的全局变量拥有外部链接属性,可以被其他文件引用和访问。而用extern修饰const全局变量后(指的是在定义const全局变量时就用extern修饰,这是拥有外部链接属性的全局变量无需做的),就能将它的链接属性从内部链接改为外部链接,有趣的是,在C中,const全局变量默认是外部链接属性,而在C++中需要extern额外修饰。
-
头文件
-
C++头文件中到底可以放什么,没有一个确定的答案,不同的项目和编程风格可能有不同的做法。但是,一般来说,有以下几个原则。
- 头文件中应该只放变量和函数的声明,而不能放它们的定义。因为定义只能有一次,如果多个源文件包含了相同的定义,会导致多重定义的错误。
- 头文件中可以写const对象的定义。因为全局的const对象默认内部链接,所以它只在当前文件中有效。把这样的对象写进头文件中,即使它被包含到其他多个.cpp文件中,这个对象也都只在包含它的那个文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。
- 头文件中可以写内联函数(inline)的定义。因为内联函数会在编译时展开,而不是在链接时调用,所以不会产生多重定义的错误。
- 头文件中可以写类(class)的定义。因为类的定义本质上是声明了类的成员变量和成员函数,而不是分配了内存空间。
- 头文件中可以写模板(template)的定义。因为模板需要在编译时根据实际参数类型生成对应的代码,所以不能分离到源文件中。
-
头文件中应该尽量避免重复包含(include)。为了防止一个头文件被多次插入到单个 .cpp 文件中,可以使用预处理指令(#ifndef, #define, #endif)(称为防卫式声明)或者#pragma once来保证头文件只被包含一次。值得注意的是,这样做可以保证的是在同一个编译单元中(一个cpp文件加上这个文件的所有头文件就是一个编译单元),一个头文件只被包含一次。若是不同cpp文件都包含了同一个头文件,这个头文件仍然会被多次包含(但这种多次包含正是头文件存在的意义,头文件就是为了复用声明代码)。
-
一文读懂C++ extern 链接属性 头文件的要点和关系
最新推荐文章于 2024-07-18 10:43:05 发布