一,声明与定义的区别
声明是将一个名称引入程序。定义提供了一个实体在程序中的唯一描述,涉及到内存空间的分配以及初始值的设定。声明和定义有时是同时存在的。
1,定义也是声明,extern声明不是定义,即不分配存储空间。
int a = 10; //定义就是声明
extern int b; //声明,不是定义
注意:如果使用extern关键字时,对变量进行了初始化,那就是定义。
extern int b = 20; //是定义
2,下列情况下,声明仅仅是声明
1: 仅仅提供函数原型:void display();
2: extern int a;
3: class A;
4: typedef 声明;
5: 在类中定义的静态数据成员的声明
例如:
class A{
public:
static int a; //声明
};
3,下列情况下,定义仅仅是定义
1: 在类定义之外,定义并初始化一个静态数据成员。如 int A::a = 0;
2: 在类外定义非内联成员函数。
二,内部链接与外部链接
在编译时,编译器只检测程序语法和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成目标文件。而在链接程序时,链接器会在所有的目标文件中找寻函数的实现。如果找不到,那到就会报链接错误码。链接把不同编译单元产生的符号联系起来。有两种链接方式:内部链接和外部链接。
1,内部链接:
如果一个符号名对于它的编译单元来说是局部的,并且在链接时不可能与其他编译单元中的同样的名称相冲突,那个这个符号就是内部链接。内部链接意味着对此符号的访问仅限于当前的编译单元中,对其他编译单元都是不可见的。
2,外部链接:
在一个多文件的程序中,如果一个符号在链接时可以和其他编译单元交互,那么这个名称就有外部链接。外部链接意味着该定义不仅仅局限在单个编译单元中。
3,函数与变量具有的连接性
全局变量、非内联成员函数、非内联函数、非静态自由函数都具有外部链接。
使用const、static关键字声明的函数或变量具有内部链接。
4,在头文件中可以包含的内容
声明仅仅是将一个符号引入到一个作用域。而定义提供了一个实体在程序中的唯一描述。在一个给定的作用域中重复声明一个符号是可以的,但是却不能重复定义,否则将会引起编译错误。
a, 将具有外部链接的定义放在头文件中几乎都是编程错误。因为如果该头文件中被多个源文件包含,那么就会存在多个定义,链接时就会出错。
b, 在头文件中放置内部链接的定义却是合法的,但不推荐使用的。因为头文件被包含到多个源文件中时,在每个编译单元中有自己的实体存在。大量消耗内存空间,还会影响机器性能。