2.9 编写自己的头文件
前言
-
- 为了允许把程序分成独立的逻辑块,C++支持所谓的分别编译
- 程序可以由多个文件组成
2.9.1 设计自己的头文件
-
- 头文件为相关声明提供了一个集中存放的位置
- 头文件一般包含
- 类的定义
- extern变量的声明
- 函数的
- 使用或者定义上面的实体的文件,需要包含头文件
- 如何编译和连接多个源文件
- g++ -c main.cc Sales_item.cc -o main
- 假设只是修改了main.cc这个源文件,那还要一起重新编译Sales_item.cc这个文件,多麻烦
- 编译器提供了分别编译每一个文件的方法,
- 通常这个过程产生.o文件,.o的扩展名表示的是该文件含有目标代码
- 编译器允许我们把目标文件(.o)连接在一起,生成可执行文件
- g++ -c main.cc
- g++ -c Sales_item.cc
- g++ main.o Sales_item.o -o main
- 生成了mian可执行文件
一、头文件用于声明,而不是用于定义
-
- 在设计头文件时,记住定义和声明的区别是很重要的;
- 定义只能出现一次
- 声明可以出现多次
- 下面语句是一些定义,不应该放在头文件中
- extern int ival = 10;
- double fica_rate;
- 如果在另一个文件中,又重新定义了ival变量,那么会导致多重定义连接错误。
- 因为,一般头文件会包含在多个源文件中,所以不应该含有变量的定义。
- 因为在每个源文件包含头文件,在实际编译过程中,都会用头文件的真实的文件内容,去替换#include "头文件"
- 如果在头文件中包含了变量的定义,那么在很多源文件中,进行头文件内容的替换时,会有重复的变量的定义。
- 但是,也有一些例外,这里需要注意一下就行,后面在进行解释:
- 在头文件中可以定义类
- 值在编译时,就已经知道的const对象
- inline函数
- 在设计头文件时,记住定义和声明的区别是很重要的;
二、一些const对象定义在头文件中
-
- const变量默认时,是定义该变量的文件的局部空间
- 常量表达式是编译器在编译时,就能计算出结果表达式,
- 整型字面值常量是常量表达式
- 当const整型变量通过常量表达式自我初始化时,这个const整型变量就可能是常量表达式
- 什么意思,
- 举个例子,const int c = 1;
- const整型变量通过常量表达式1,进行初始化,以后可以认为c这个const变量就是一个常量表达式
- C++中任何变量都只能定义一次,原因?
- 因为在定义变量时,会分配存储空间
- 所有对该变量的使用,都会关联到同一存储空间上。
- int i = 5;
- a.cc使用了i变量,b.cc使用了i变量,c.cc使用了i变量
- 所有cc文件对变量的使用,都会关联到同一个存储空间上。
- 当const变量是用常量表达式进行初始化时,可以保证所有的变量都具有相同的值。
- 其实,在实际中,大部分编译器都会用相应的常量表达式来替换这些const变量的使用。
- 所以在实际中,对于使用常量表达式初始化的const变量,没有实际的存储空间
- const int i = 5;
- 在内存中没有实际的内存空间去存放它
- 而是,在使用时,用常量表达式5来替换const int i变量。
- const变量的初始化
- 常量表达式初始化,const int i = 5;
- const int j = func(a,b);对于这种情况,
- 不是使用常量表达式初始化const变量,
- 这种定义,不应该放在头文件中,
- 应该和其他变量一样,放在源文件中定义,并进行初始化。
- 应该在头文件中添加extern声明,使其可以被多个文件共享
2.9.2 预处理器简单介绍
前言
-
- #include 是C++预处理器的一部分
- 预处理器处理程序的源码,在编译器之前运行
- 预处理器 ---》编译器 ---》
- 在实际包含头文件的源文件中,预处理器用头文件的内容去代替每个#include
- 我们自己写的头文件存储在文件中,系统的头文件可能以更高效的方式存储,例如二进制???仅仅是猜测啊
一、头文件经常需要其他头文件
-
- 头文件经常include其他头文件
- 一个头文件被include到同一个源文件多次也不稀奇
- 设计头文件时,应该使头文件可以被多次包含在同一源文件中,
- 我们必须保证,多次包含同一个头文件不会引起该头文件定义的类和对象被多次定义
- 如何做到上面的保证呢?使用预处理器定义头文件保护符
- 用于避免在已经见到头文件的情况下,重新处理该头文件的内容
二、避免多重包含
-
- 预处理器允许我们自己定义变量
- 预处理器变量通常用全部大写字母表示
- 预处理器变量有两种状态:
- 已定义
- 未定义
- #define接受一个名字,并定义该名字为预处理器变量
- #ifndef 检测指定的预处理器变量是否为未定义,如果预处理器变量未定义,那么跟在其后的所有指示都被处理掉,知道出现#endif
- 举个例子,可以使用下面的方法来避免多次包含同一个头文件
- #ifndef SALESITEM_H
- #define SALESITEM_H
- ....定义Sales_item 类
- #endif
三、使用自定义的头文件
-
- 头文件在<>内,认为该头文件是标准头文件,编译器会在预定的位置查找该头文件,预定的位置可以通过设置查找路径环境变量或者命令行选项来修改
- 头文件见在“”内,认为是非系统的头文件,查找开始于源文件所在的路径。
时间: 2024-10-05 19:32:14