【fishing-pan:https://blog.csdn.net/u013921430转载请注明出处】
1. 头文件的作用
在C++中主要有两类文件.cpp文件和.h(还有.hpp文件);在进行编译的过程中,C++的编译器只会对cpp文件进行编译,.h文件不会参与编译,而是被包含到引用了头文件的cpp文件中。例如,#include "A.h",这样有一个好处,就是在一处进行了声明的变量或者函数能够被多个文件引用,不需要声明多次。
虽然不参与编译,但是其实在头文件们被包含后,某种意义上来说,他们被编译了许多次;
根据“一个变量只能被定义一次”的原则,我们在使用头文件的时候需要一个注意事项;
2. 头文件使用的注意事项
1. 不要随意在头文件定义变量和函数;
一般在头文件中,只声明函数和变量,而不进行定义,例如
声明: extern int a;和void f();
定义:如果写上int a;或者void f() {}
如果进行了定义,一旦这个头文件被两个及以上的cpp文件引用,就会发生编译错误; 但是也有例外的情况,常量对象(const对象)在声明的时候就需要进行赋值(即进行定义)。因为全局的const对象默认只在当前文件中有效。把这样的对象写进头文件中,即使它被包含到其他多个.cpp文件中,这个对象也都只在包含它的文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。
此外,头文件中可以定义内联函数(inline)和类(class)的定义,包括类的成员函数的定义(注:需要放在类内部);
但是很多时候,我们会不自觉的在头文件中定义变量,或者说我就想在头文件里面定义(虽然非常不建议这样做),怎么办呢?
使用 #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。
大家自己写头文件的时候应该养成加入这三句话的习惯,可以免去很多不必要的麻烦;
2. 头文件中类的相互引用;
类在C++中经常被使用,类的所带来的继承和多态让它很强大,可以实现很多功能。大家都知道,父类和子类之间不能相互继承;但是在有些时候,两个类之间需要互相引用或者说父子之间不得不相互包含对方类型的变量,问题就来了,那怎么办呢?
我们看下面这段代码;
#ifndef CB_H
#define CB_H
#include"CA.h"
//class A;
class B
{
A *ss;
};
#endif
#ifndef CA_H
#define CA_H
#include"CB.h"
class B;
class A
{
B *ss;
//B s;
};
#endif
在代码中类A中有类B的变量,类B中也有A的变量,
因为我们在CA.H的定义中除了#include "CB.h"还加入了class B,这样一行,这段代码并不会报错,大家可以试试注释掉这样的一行,看看是否会报错。
这样一个前向申明就避免了编译错误,否则B是无法被识别的数据类型;
那么又有一个问题了,为什么实在CA.H中加入class B,而不是在CB.H中加入class A呢?
其实都是一样的,这取决于在各个CPP文件中你先引用(#include)哪个头文件;
例如我是先引用的CB_H;根据引用关系先编译“CB.h”,而在“CB.h”中又引用了“CA.h”。这时候又编译“CA.h”,然后A中又有了B类的数据类型,这个是未知的,所以先声明一个 class B;这样的一个声明就告诉编译器,class B 在别处定义。
#include "CB.h"
#include "CA.h"
#include <iostream>
using namespace std;
void main()
{
system("pause");
return;
}
所以就在CA.h中加入class B,若两者交换了位置,相应的就需要在CB.h中加入class A。或者可以将class A也在“CB.h”中加上,这样的话,不用担心头文件的#include顺序问题。
已完。。。
相关博客:C++中的头文件(.h)—详解(1)、C++中的头文件(.h)—详解(2)