1.在C++中对函数进行声明的作用是,方便其它.cpp文件调用,复用代码;
2.如果一个函数只希望在本.cpp文件中使用,不希望其它.cpp文件调用,那么只需要在本.cpp文件中,将该函数声明为静态static (可以避免不同.cpp,对该函数重复定义问题),如果没有出现重复定义,也必须添加static,因为函数默认为extern的,可以在其它.cpp中调用extern 函数名,来进行引用;
3.
.h
int nDefNum[]; //这是数组的声明 默认为extern;一处定义多出引用不会出现重定义问题
int DefineNum[10]; //这是在头文件中定义函数 多处引用会导致重定义问题
extern int DefineNum[10]; //这是显示声明数组DefineNum为外部定义,
以下情况是不引用对应的头文件:
<1> 全局变量在外部使用声明时,extern关键词是必须的。如果变量无extern修饰且没有显式的初始化,同样成为变量的定义,而编译器在此标记存储空间执行时加载入内存并初始化为0。
<2> 而局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈部分分配内存。
<3> 全局变量或函数本质上讲没有区别,函数名是指向函数二进制块开头处的指针。而全局变量是在函数外部声明的变量。函数名也在函数外,因此函数也是全局的。
<4>函数的声明extern关键词是可有可无的,因为函数本身不加修饰的话就是extern的;但是引用的时候一样是需要声明的。
<5>谨记:声明可以多次(头文件、源文件中,都可以声明),定义只能一次;
头文件、源文件的后缀名,可以任意,习惯为.h .c .cpp
.h
int A;
很糟糕的是,这里的int A是个全局变量的定义,所以如果这个头文件被多次引用的话,你的A会被重复定义,显然语法上错了。只不过有了这个#ifndef的条件编译,所以能保证你的头文件只被引用一次,不过也许还是会岔子,但若多个c文件包含这个头文件时还是会出错的,因为宏名有效范围仅限于本c源文件,所以在这多个c文件编译时是不会出错的,但在链接时就会报错,说你多处定义了同一个变量。【宏名有效范围仅限于本c源文件!】
extern解释
extern int a; //声明一个全局变量a
int a; //定义一个全局变量a
extern int a =0 ;//定义一个全局变量a 并给初值。
int a =0; //定义一个全局变量a,并给初值,
第四个 等于 第 三个,都是定义一个可以被外部使用的全局变量,并给初值。糊涂了吧,他们看上去可真像。但是定义只能出现在一处:也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。
当你要引用一个全局变量的时候,你就要声明:extern int a;这时候extern不能省略,因为省略了就变成int a;,这是一个定义,不是声明。(外部引用,如果包含头文件,源文件中不需要加extern,但是一般不会在头文件中声明全局变量,因为头文件会被到处包含,全局变量被多次无意义声明);
<2>函数(函数定义和声明时都可以将extern省略)
对于函数也一样,也是定义和声明。定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。 但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体,所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行。两者如此不同,所以省略了extern也不会有问题。比如:
int fun(void)
{
return 0;
}
很好,我们定义了一个全局函数int fun(void);
我们对它做了个声明,然后后面就可以用了,加不加extern都一样
我们也可以把对fun的声明 放在一个头文件里,最后变成这样:
int fun(void);//函数声明放在头文件,省略了extern,完整些是extern int fun(void);
int fun(void)
{
return 0;
}//一个完整的全局函数定义,因为有函数体,extern同样被省略了
总结:
1.头文件.h和源文件.cpp的说法和用法,只是约定的,实际上编译器,以函数和变量的声明和定义为准,不会辨别文件后缀名;声明只是告诉编译器,该函数或者变量的特性,该去哪里找该函数或者变量的定义;定义才是编译器关注的内容!
2.在源文件中,全局变量如果没有特殊说明,最好声明为static,否则就是默认外部变量,这时候多处引用该变量,如果添加extern是正确用法,没有添加extern就是重定义;全局函数也一样!
extern “C” 不但具有传统的声明外部变量的功能; 还具有告知C++链接器使用C函数规范来链接的功能; 还具有告知C++编译器使用C规范来命名的功能。
由于extern c不能被C编译器所识别,所以所有使用extern c的地方,都应该先判断当前编译器是不是用c++的