什么应该放在头文件里
头文件为相关声明提供了一个集中存放的位置。头文件一般包含类的定义、枚举的定义、extern变量的声明、函数的声明、const int的定义、inline函数的定义。使用或者定义这些实体的文件要包含适当的头文件。
头文件用于声明,而不用于定义
当设计头文件时,记住定义和声明的区别是很重要的。定义只可以出现一次,而声明可以出现多次。下列语句是定义,所以不应该放在头文件里:
Double fica_rate; // 没有extern关键字,所以也是定义
因为以上两个语句都是定义(其实还因为全局变量默认的连接类型是extern,即外连接),所以,当同一个程序中有两个或两个以上文件含有上述任一个定义都会导致多重定义链接错误。
因为头文件被设计用来包含在多个源文件中,所以不应该含有变量或者函数的定义。
对于头文件不应该含有定义这一规则,有三个例外:类定义、枚举的定义、值在编译时就已知的const对象、inline函数。这些实体可以在多个源文件中定义,只要每个源文件中的定义是相同的。
在头文件中定义这些实体,是因为编译器需要它们的定义(不只是声明)来产生代码。例如:为了产生能定义和使用类对象的代码,编译器需要知道组成该类型的数据成员。同样还需要知道能够在这些对象上执行的操作。而类定义正好提供了这些信息。
const对象(变量)默认是定义该变量的文件的局部变量,连接类型为内连接。所以,当多个源文件include包含同一个含有const对象定义的头文件时,不会产生多重定义的链接错误。这是因为,实质上每个包含该头文件的源文件都有了自己的const变量,都为它分配的存储空间,其名称和值都一样。同时,因为const变量默认连接类型是内连接,所以不会产生多重定义的链接错误。
在大部分的编译器实现中,编译器都会用相应的常量表达式来替换对这些const变量的使用。所以,在实践中不会有任何存储空间用于存储 用常量表达式初始化的const变量。
如果const变量不是用常量表达式初始化的,那么它就不应该在头文件中定义。它应该和其他的变量一样,应该定义在一个源文件中并初始化,在头文件中为它添加extern声明,以便被多个文件共享。
外连接
全局变量、全局函数默认是外连接的。
内连接
类定义、全局常量、const对象(变量)、typedef类型、宏定义 默认为内连接的。另外,定义时被显示加上static关键字的全局变量和全局函数,具有文件作用据,连接类型也为内连接。
默认为内连接的标识符,如果显示加上extern关键字,即变成外连接。
外连接标识符的使用
在使用外连接的实体的时候,可以include其定义所在的文件(错误的方法,产生链式错误:多重定义),还可以include其声明所在的文件。也可以采用第三种方法:直接在使用外连接实体的文件中,直接对外连接实体进行一次extern声明(若外连接实体类型为函数,则不用extern关键字,函数原型OK了)。