一、C++中包含的主要文件
1.1 .cpp文件
- .cpp 文件被称作 C++ 源文件
1.2 .h文件
- .h 文件则被称作 C++ 头文件
1.3 .so文件
二、头文件简介
2.1 头文件的作用
所谓的头文件,其实它的内容跟 .cpp 文件中的内容是一样的,都是 C++ 的源代码。但头文件不用被编译。我们把所有的函数声明全部放进一个头文件中,当某一个 .cpp 源文件需要它们时,它们就可以通过一个宏命令 “#include” 包含进这个 .cpp 文件中,从而把它们的内容合并到 .cpp 文件中去。当 .cpp 文件被编译时,这些被包含进去的 .h 文件的作用便发挥了。
2.2 头文件的分类
按照来源的不同,有两种类型的头文件:程序员编写的头文件和标准库(编译器或者其他库的头文件)。
- 对于程序员自己编写的头文件的包含使用"filename";
#include "CA.h"
- 对于标准库头文件的包含使用< filename>;
#include <iostream>
2.3 头文件的内容
- 下面的这些内容应该放在头文件中:函数原型声明、全局变量声明、自己定义的宏和类型等。
- 下面这些内容不应该放在头文件中:全局变量的定义、外部变量的定义、静态变量和静态函数的的定义、在类体之外的类成员函数的定义等。
头文件应该包含和不应该包含什么内容,都是为了满足头文件被多个源文件包含而不引发编译错误。
- 头文件中可以写const对象的定义
因为全局的const对象默认只在当前文件中有效,把const对象写进头文件中,即使它被包含到其他多个.cpp文件中,这个对象也都只在包含它的文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。同理,static对象的定义也可以放进头文件。
- 头文件中可以写内联函数(inline)的定义
inline函数是需要编译器在遇到它的地方根据它的定义把它内联展开的,而并非是普通函数那样可以先声明再链接的,内联函数并不会参与链接,所以编译器就需要在编译时看到内联函数的完整定义才行。C++规定,内联函数可以在程序中定义多次,只要内联函数的定义在一个.cpp文件中只出现一次,并且在所有的.cpp文件中,这个内联函数的定义是一样的,就能通过编译。那么把内联函数的定义放进一个头文件中就能满足以上的要求,何乐不为呢。
- 头文件中可以写类 (class)的定义
在程序中创建一个类的对象时,编译器只有在这个类的定义完全可见的情况下,才能知道这个类的对象应该如何布局,所以,关于类的定义的要求,跟内联函数是基本一样的。所以把类的定义放进头文件,在使用到这个类的.cpp文件中去包含这个头文件,是一个很好的做法。类的定义中包含着数据成员和成员函数。数据成员是要等到具体的对象被创建时才会被定义,被分配空间,但函数成员却是需要在一开始就被定义的。
我们可以直接把函数成员的实现代码也写进类定义中。在C++的中,如果函数成员在类的定义体中被定义,那么编译器会视这个函数为内联的。因此是合法的。注意一下,如果把函数成员的定义写在类定义的头文件中,而没有写进类定义范围内,这是非法的,因为这个函数成员此时就不是内联的了,如果该头文件被两个及以上的.cpp文件同时包含,这个函数成员就被重定义了。
2.4 头文件的使用注意事项
- 不要随意在头文件定义变量和函数: 一般在头文件中,只声明函数和变量,而不进行定义,例如
声明: extern int a;和void f();
定义:如果写上int a;或者void f() {}
- 如果想在头文件中定义变量:使用 #ifndef,#define, #endif或者使用#pragma once
#ifndef CB_H //#pragma one
#define CB_H
#include"CA.h"
class B
{
A *ss;
};
#endif
很简单的几行,就能够告诉编译器,这个头文件只编译一次,所以不会多次定义;
在大家使用Visual Studio的时候,若是使用控制台程序,生成的头文件中会自动含有 #ifndef,#define, #endif。
大家自己写头文件的时候应该养成加入这三句话的习惯,可以免去很多不必要的麻烦;
- 头文件中类的相互引用