由多个文件组成的程序需要一种方法连接名字的使用和声明,在C++中是通过头文件实现的。头文件一般包括类的定义,extern 变量的声明和函数的声明。使用或定义这些实体的文件要包含适当的头文件。 头文件的正确使用有两个好处:保证所有文件使用给定实体的同一声明;当声明需要修改时,只有头文件需要更新。在定义头文件时要注意头文件中所做的声明在逻辑上应该是适于放在一起的,否则,编译头文件会花费较长时间。 使用头文件时需要注意以下几点:
当定义头文件时,记住定义和声明的区别是很重要的。定义只可以出现一次,而声明可以出现多次。因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义,否则会造成在同一个程序对同一个变量或函数的多次定义。下列语句是定义,所以不应该放在头文件中: extern int ival = 10; double ix; 对头文件不应该含有定义这一规则,有三个例外。头文件可以定义类,值在编译时就已经知道的const对象和inline函数。这些实体可以在多个源文件中定义,只要每个源文件中的定义是相同的。 在头文件中定义这些实体,是因为编译器需要它们的定义来产生代码。例如:为了产生能定义或使用类的对象的代码,编译器需要知道组成该类型的数据成员,同样还需要知道能够在这些对象上执行的操作。对于const对象,作以下说明: 除非特别说明,在全局作用域声明的const变量默认为是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定const变量为extern,就可以在整个程序中访问const对象。例如: //在file1中定义变量ix extern const int ix = 5; //在file2中我们可以这样使用它 extern const int ix; for (int index = 0; index != ix; ++index) {…} 通过对const变量进行为编译器可见的初始化式初始化后,const变量成为常量表达式。为了能够让const变量和它的初始化式在每个文件中都可见,一般都把这样的const变量定义在头文件中,从而使包含该头文件的文件都可以使用相同的常量值。无论该const变量何时使用,编译器都可以看见其初始化式。在C++中任何变量都只能定义一次,定义会分配存储空间,而所有对该变量的使用都关联到同一存储空间,因为const对象默认为定义它的文件的局部变量,所以把它们定义放在头文件中是合法的。 如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义,相反,它应该和其他变量一样,该const变量应该在一个源文件中定义并初始化,然后在头文件中为它添加extern声明,以使其能被多个文件共享。
#include设施是C++预处理器的一部分,它只接受一个参数:头文件名。预处理器用指定的头文件的内容替代每个#include.
头文件经常#include其他头文件,头文件定义的实体经常使用其他头文件的设施,在同一源文件中还可能多次包含同一头文件。比如我们自己定义了一个Query.h的头文件,该头文件中包含了string的头文件。同时,我们在编写源代码时也使用了string库,这样string 库就包含了两次:一次是通过程序本身直接包含,一次是通过包含Query头文件间接包含。 设计头文件时,应使其可以多次包含在同一源文件中,我们必须保证多次包含同一头文件不会引起该头文件中定义的类和对象被多次定义,使得头文件安全的通用做法,是使用预处理器定义头文件保护符来避免在已经见到头文件的情况下重新处理该头文件的内容。
为了避免名字冲突,预处理变量经常用全大写字母表示。预处理变量有两种状态:已定义或未定义。定义预处理器变量和检测其状态所用的预处理指示不同。#define指示接受一个名字并定义该名字为预处理变量。#ifndef指示检测指定的预处理器变量是否未定义。如果预处理器变量未定义,那么跟在其后的所有指示都被处理,直到出现#endif。可以使用这种方法来预防多次包含同一头文件。 #ifndef QUERY_H #define QUERY_H //定义query.h中的内容 #endif
条件指示 #ifndef QUERY_H 测试 QUERY_H预处理器变量是否未定义。如果 QUERY_H未定义,那么#ifndef测试成功,跟在#ifndef后面的所有行都被执行,直到发现#endif.相反,如果QUERY_H已定义,那么#infdef指示测试为假,该指示和#endif指示之间的代码都被忽略。通常情况下,我们用定义在头文件中的实体(如类)来命名预处理器变量来避免预处理器变量重名的问题。通过使用类名来组成头文件和预处理器变量的名字,可以使得很可能只有一个文件将会使用该预处理器变量。
#include指示接受以下两种形式: #include<iostream>
#include"query.h"
如果头文件名括在尖括号< >里,那么认为该头文件是标准头文件。编译器会在预定义的位置集查找该头文件,这些预定义的位置可以通过设置查找路径环境变量或者通过命令行选项来修改。如果头文件名括在一对引号里,那么认为它是非系统头文件,非系统头文件的查找通常开始于源文件所在的路径。
新闻热点
疑难解答
图片精选