“重复包含”顾名思义,即头文件在一个源文件或多个源文件中被多次包含,使得在编译时需要对该头文件中的代码进行重复编译,显然这是一种重复劳动,缺乏效率,而且还可能引起一系列问题。如果对我给出的解释感到晕乎,那么先来看几个重复包含引发错误的例子:
(1)C语言中的重复包含
例1.1.1(单源文件的重复包含):
创建一个源文件main.c,一个头文件head.h,如下:
//****************************
//* 头文件:head.h *
//****************************
int g_iNum = 1;
-
-
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include "head.h"
- #include "head.h"
-
-
- int main()
- {
- printf(“%d\n”, g_iNum);
- system(“pause”);
- return 0;
- }
//****************************
//* 源文件:main.c *
//****************************
#include <stdio.h>
#include <stdlib.h>
#include "head.h"
#include "head.h"
// 重复包含头文件head.h
int main()
{
printf(“%d\n”, g_iNum);
system(“pause”);
return 0;
}
对例1.1.1的进行编译,编译器报错,提示类似“redefined”(重复定义)这样的错误。这是因为头文件head.h在源文件main.c中重复包含两次,编译器处理时,头文件head.h在源文件main.c中被展开,由于是展开两次,因此语句“int g_iNum = 1;”出现两次,大致情况如下:
-
-
-
- int g_iNum = 1;
- int g_iNum = 1;
-
-
- int main()
- {
- printf(“%d\n”, g_iNum);
- system(“pause”);
- return 0;
- }
// 其他部分
int g_iNum = 1;
int g_iNum = 1;
// 重复定义
int main()
{
printf(“%d\n”, g_iNum);
system(“pause”);
return 0;
}
显然这样是错误的,int型变量g_iNum在源文件main.c中连续定义两次。当然,这种错误一般人都不会犯,谁会故意将一个头文件在同一个源文件中包含两次呢?但是,如果将一个头文件包含到另一个头文件里,再将这两个头文件分别包含在一个源文件中,这样所产生的错误就比较常发生了,而且不容易察觉到,也许你就曾经犯过这样的错误。来看一下这种错误的例子。
例1.1.2(单源文件的头文件嵌套包含):
创建一个源文件main.c,两个头文件head1.h和head2.h,如下:
//******************************
//* 头文件:head1.h *
//******************************
int g_iNum1 = 1;
-
-
-
-
-
- #include “head1.h”
-
-
- int g_iNum2 = 2;
//******************************
//* 头文件:head2.h *
//******************************
#include “head1.h”
// 嵌套包含头文件head1.h
int g_iNum2 = 2;
-
-
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include "head1.h"
- #include "head2.h"
-
- int main()
- {
- printf(“%d\n”, g_iNum);
- system(“pause”);
- return 0;
- }
//****************************
//* 源文件:main.c *
//****************************
#include <stdio.h>
#include <stdlib.h>
#include "head1.h"
#include "head2.h"
int main()
{
printf(“%d\n”, g_iNum);
system(“pause”);
return 0;
}
在例1.1.2中,如果单独观察每个文件,不容易发现问题所在,需要假想编译器处理时的情况。首先头文件head1.h在源文件main.c中展开,于是源文件main.c中有拥有了语句“int g_iNum = 1;”。接着展开头文件head2.h,由于头文件head2.h中包含了头文件head1.h,故再次对头文件head1.h进行展开。此时,源文件main.c中将拥有两条“int g_iNum = 1;”语句,显然int型变量“g_iNum”被重复定义,编译器报错。
一般的解决方案是将头包含命令“#include “head1.h””从头文件head2.h中删除。
(2)C++中的重复包含
因为C++是兼容C语言的,所以上面的两个例子产生的问题在C++中同样会发生。而较之于单纯的C语言,C++中重复包问题更复杂。
我们通常在定义类时,将类的声明和实现分开,声明部分放在头文件中,实现部分放在源文件中。这是一种好习惯,但是没处理好却也会让人大伤脑筋。来看下面的几个例子:
例1.1.3(单源文件的类声明头文件嵌套包含):
创建工程,定义一个点类CPoint,将声明和实现分别放在CPoint.h和CPoint.cpp中,定义一个线类CLine,将声明和实现分别放在CLine.h和CLine.cpp中,主函数在源文件main.cpp中:
-
-
-
-
-
-
- class CPoint
- {
- protected:
- double m_dX;
- double m_dY;
- public:
- CPoint(double x = 0, double y = 0);
- virtual void set(double x, double y);
- double getX();
- double getY();
- };
//********************************************
//* 头文件:CPoint.h *
//* 描 述:点类CPoint的声明 *
//********************************************
class CPoint
{
protected:
double m_dX;
double m_dY;
public:
CPoint(double x = 0, double y = 0);
virtual void set(double x, double y);
double getX();
double getY();
};
-
-
-
-
-
-
- #include "CPoint.h"
-
- CPoint::CPoint(double x, double y):m_dX(x), m_dY(y)
- {
- }
-
- void CPoint::set(double x, double y)
- {
- m_dX = x;
- m_dY = y;
- }
-
- double CPoint::getX()
- {
- return m_dX;
- }
-
- double CPoint::getY()
- {
- return m_dY;
- }
//********************************************
//* 源文件:CPoint.cpp *
//* 描 述:点类CPoint的实现 *
//********************************************
#include "CPoint.h"
CPoint::CPoint(double x, double y):m_dX(x), m_dY(y)
{
}
void CPoint::set(double x, double y)
{
m_dX = x;
m_dY = y;
}
double CPoint::getX()
{
return m_dX;
}
double CPoint::getY()
{
return m_dY;
}
-
-
-
-
-
-
- #include "CPoint.h"
-
-
- class CLine:public CPoint
- {
- protected:
- double m_dLength;
- public:
- CLine(double x = 0, double y = 0, double l = 0);
- void set(double x, double y, double l);
- double getLength();
- };
//*********************************************************************************
//* 头文件:CLine.h *
//* 描 述:线类CLine的声明,CLine由CPoint的派生而来。 *
//*********************************************************************************
#include "CPoint.h"
// 头文件嵌套包含
class CLine:public CPoint
{
protected:
double m_dLength;
public:
CLine(double x = 0, double y = 0, double l = 0);
void set(double x, double y, double l);
double getLength();
};
-
-
-
-
-
-
- #include "CLine.h"
-
- CLine::CLine(double x, double y, double l):CPoint(x, y)
- {
- m_dLength = l;
- }
-
- void CLine::set(double x, double y, double l)
- {
- CPoint::set(x, y);
- m_dLength = l;
- }
-
- double CLine::getLength()
- {
- return m_dLength;
- }
//*******************************************
//* 源文件:CLine.cpp *
//* 描 述:线类CLine的实现 *
//*******************************************
#include "CLine.h"
CLine::CLine(double x, double y, double l):CPoint(x, y)
{
m_dLength = l;
}
void CLine::set(double x, double y, double l)
{
CPoint::set(x, y);
m_dLength = l;
}
double CLine::getLength()
{
return m_dLength;
}
-
-
-
-
-
- #include <iostream>
- #include <stdlib.h>
- #include "CPoint.h"
- #include "CLine.h"
-
- using namespace std;
-
- int main()
- {
- CLine line;
-
- line.set(1.2, 2.3, 3.4);
- cout << line.getX() << endl;
- cout << line.getY() << endl;
- cout << line.getLength() << endl;
- system(“pause”);
- return 0;
- }
//*******************************
//* 源文件:main.cpp *
//*******************************
#include <iostream>
#include <stdlib.h>
#include "CPoint.h"
#include "CLine.h"
using namespace std;
int main()
{
CLine line;
line.set(1.2, 2.3, 3.4);
cout << line.getX() << endl;
cout << line.getY() << endl;
cout << line.getLength() << endl;
system(“pause”);
return 0;
}
对例1.1.3的工程进行编译,编译器报错,提示“CPoint”类重复定义。问题出在头文件CLine.h中,由于在其中嵌套包含了头文件CPoint.h,使得在编译源文件main.cpp时出错。首先,编译器遇到头包含命令“#include "CPoint.h"”,将头文件CPoint.h在源文件main.cpp中展开。接着,遇到头包含命令“#include "CLine.h"”,也将头文件CLine.h在源文件main.cpp中展开。由于头文件CLine.h中有头包含命令“#include "CPoint.h"”,于是再次将头文件CPoint.h源文件main.cpp中展开。此时,点类CPoint的声明部分在源文件main.cpp中出现了两次,重复了,于是报错。
对于这种错误,一般有两种解决方案。一是将头文件CLine.h中的头包含命令“#include "CPoint.h"”删除,再在源文件CLine.cpp中的头包含命令“#include “CLine.h””之上添加头包含命令“#include "CPoint.h"”。二是直接将源文件main.cpp中的头包含命令“#include "CPoint.h"”删除。对于简单的几个文件而言,此方案足矣。然而对于一个包含很多文件的大工程工程,此法并非良策。在文章后面将会介绍到一种优越的解决方案。
如果是将类的声明和实现都放在一个文件中会怎样呢?看下面例1.1.4:
例1.1.4(类的声明和实现不分开):
修改例1.1.3中的错误,并将类的声明和定义都放在同一个头文件中。
-
-
-
-
-
-
-
-
- class CPoint
- {
- protected:
- double m_dX;
- double m_dY;
- public:
- CPoint(double x = 0, double y = 0);
- virtual void set(double x, double y);
- double getX();
- double getY();
- };
-
-
-
- CPoint::CPoint(double x, double y):m_dX(x), m_dY(y)
- {
- }
-
- void CPoint::set(double x, double y)
- {
- m_dX = x;
- m_dY = y;
- }
-
- double CPoint::getX()
- {
- return m_dX;
- }
-
- double CPoint::getY()
- {
- return m_dY;
- }
//*****************************************************
//* 头文件:CPoint.h *
//* 描 述:点类CPoint的声明和实现 *
//*****************************************************
// 类的声明部分
class CPoint
{
protected:
double m_dX;
double m_dY;
public:
CPoint(double x = 0, double y = 0);
virtual void set(double x, double y);
double getX();
double getY();
};
// 类的实现部分
CPoint::CPoint(double x, double y):m_dX(x), m_dY(y)
{
}
void CPoint::set(double x, double y)
{
m_dX = x;
m_dY = y;
}
double CPoint::getX()
{
return m_dX;
}
double CPoint::getY()
{
return m_dY;
}
-
-
-
-
-
-
- #include "CPoint.h"
-
-
-
- class CLine:public CPoint
- {
- protected:
- double m_dLength;
- public:
- CLine(double x = 0, double y = 0, double l = 0);
- void set(double x, double y, double l);
- double getLength();
- };
-
-
-
- CLine::CLine(double x, double y, double l):CPoint(x, y)
- {
- m_dLength = l;
- }
-
- void CLine::set(double x, double y, double l)
- {
- CPoint::set(x, y);
- m_dLength = l;
- }
-
- double CLine::getLength()
- {
- return m_dLength;
- }
//***************************************************************
//* 头文件:CLine.h *
//* 描 述:线类CLine的声明和实现,CLine由CPoint的派生而来。*
//***************************************************************
#include "CPoint.h"
// 类的声明部分
class CLine:public CPoint
{
protected:
double m_dLength;
public:
CLine(double x = 0, double y = 0, double l = 0);
void set(double x, double y, double l);
double getLength();
};
// 类的实现部分
CLine::CLine(double x, double y, double l):CPoint(x, y)
{
m_dLength = l;
}
void CLine::set(double x, double y, double l)
{
CPoint::set(x, y);
m_dLength = l;
}
double CLine::getLength()
{
return m_dLength;
}
-
-
-
-
-
- #include <iostream>
- #include <stdlib.h>
-
- #include "CLine.h"
-
- using namespace std;
-
- int main()
- {
- CLine line;
-
- line.set(1.2, 2.3, 3.4);
- cout << line.getX() << endl;
- cout << line.getY() << endl;
- cout << line.getLength() << endl;
- system(“pause”);
- return 0;
- }
//*******************************
//* 源文件:main.cpp *
//*******************************
#include <iostream>
#include <stdlib.h>
// 不再包含头文件CPoint.h
#include "CLine.h"
using namespace std;
int main()
{
CLine line;
line.set(1.2, 2.3, 3.4);
cout << line.getX() << endl;
cout << line.getY() << endl;
cout << line.getLength() << endl;
system(“pause”);
return 0;
}
将例1.1.4同例1.1.3比较,似乎例1.1.4更加简洁方便,可以少写些头包含命令。既然如此,那为什么平常我们会被建议将类的声明和实现分开来呢?这并不是空穴来风、混淆视听。当工程中含有多个源文件,而有两个或两个以上的源文件中包含了同一个类的头文件(包括声明和实现),那么问题就会凸显出来。为了演示这个问题,我们在例1.1.4的基础上,再加入一个源文件test.cpp和对应的头文件test.h,并在其中引用“CLine”这个类。
-
-
-
-
-
- #include <iostream>
- #include "CLine.h"
-
-
-
- using namespace std;
-
- void test()
- {
- CLine line;
-
- line.set(2.4, 1.5, 4.7);
- cout << line.getX() << endl;
- cout << line.getY() << endl;
- cout << line.getLength() << endl;
- }
//*******************************
//* 源文件:test.cpp *
//*******************************
#include <iostream>
#include "CLine.h"
// 在源文件main.c中也包含头文件CLine.h
using namespace std;
void test()
{
CLine line;
line.set(2.4, 1.5, 4.7);
cout << line.getX() << endl;
cout << line.getY() << endl;
cout << line.getLength() << endl;
}
//***************************************
//* 头文件:test.h *
//* 描 述:test.cpp中的函数声明 *
//***************************************
void test();
如果对源文件test.cpp单独编译不会出错,而当构建整个工程时却出错了,错误提示大意是CPoint类和CLine类的成员函数已经在目标文件main.obj中定义了。为什么会这样呢?让我们追随编译器的脚步来看个究竟:编译器先对每个源文件单独编译,由于源文件main.cpp和源文件你test.cpp中都有头包含命令“#include “CLine.h””,对头文件CLine.h进行展开后,在这两个源文件文件中都存在点类CPoint和线类CLine的声明和实现代码,这一点并不影响各个文件单独编译。单独编译之后得到两个目标文件main.obj和test.obj。接下来将目标文件连接为一个文件,连接过程中发现在该文件中点类CPoint和线类CLine都被定义了两次,于是就报错。
此时只得把按更正后的例1.1.3将点类CPoint和线类CLine的声明和实现分开来。因此,“将类的声明部分放在头文件中,而将实现部分放在源文件中”是很有必要的,特别是在多文件编程时。
尽管如此,然而对于类模板却是另一番景象,类模板的声明和实现需放在同一个头文件中。从网络上的资料得知,如果要将类模板的声明部分和实现部分分开的话,需要使用关键字export。但是VC6等编译器都不支持关键字export,所以目前只能将二者放在一个头文件中。
2、解决重复包含的优化方案
当一个工程的文件不多时,上述几个重复定义的解决方案并不会表现出明显的缺陷。而随着工程中文件的不断增加,这些解决方案便越发显得笨拙而费时,甚至让人无从下手。有没有更好的解决方案呢?当然是有的,否则就不会有这篇文章了!
接触过VC的朋友可能会发现,在使用AppWizard(应用程序向导)创建程序模板时会自动生成源文件StdAfx.cpp和头文件StdAfx.h。如果你的好奇心够强烈的话,也许你会百度一下,了解有关StdAfx的相关资料。在此期间,或许你对阅读这些资料时感到吃力,不知所云。既然这样,那就先撇开那堆晦涩难懂的文字,来了解一下StdAfx对我们解决重复包含问题的巨大贡献吧。下面不讲理论,只浅显地模仿StdAfx的模式来解决重复包含问题。若是理论,我也谈不来。
对于工程,我们大可不必借助程序模板,自己动手,一步步地完善一个空工程。这里就以修正后的例1.1.3为基础,进行完善。
步骤一:
再另外创建两个文件,其中一个源文件StdAfx.cpp,一个头文件StdAfx.h。(这两个文件的文件名可随意取,并不是固定的,我只是仿照了VC中自动创建的那两个文件,这样来得亲切,而且有助于理解“StdAfx”。)
步骤二:
在每个头文件的首尾处添加条件编译命令,使得每个头文件中的代码都被夹在中间,像下面这样:
-
-
-
-
-
-
-
- #ifndef CPOINT_H
- #define CPOINT_H
-
- class CPoint
- {
- protected:
- double m_dX;
- double m_dY;
- public:
- CPoint(double x = 0, double y = 0);
- virtual void set(double x, double y);
- double getX();
- double getY();
- };
-
- #endif
//***************************************
//* 头文件:CPoint.h *
//* 描 述:点类CPoint的声明 *
//***************************************
// 条件编译
#ifndef CPOINT_H
#define CPOINT_H
class CPoint
{
protected:
double m_dX;
double m_dY;
public:
CPoint(double x = 0, double y = 0);
virtual void set(double x, double y);
double getX();
double getY();
};
#endif
-
-
-
-
-
-
-
- #ifndef CLINE_H
- #define CLINE_H
-
- class CLine:public CPoint
- {
- protected:
- double m_dLength;
- public:
- CLine(double x = 0, double y = 0, double l = 0);
- void set(double x, double y, double l);
- double getLength();
- };
-
- #endif
//***************************************************************
//* 头文件:CLine.h *
//* 描 述:线类CLine的声明,CLine由CPoint的派生而来。 *
//***************************************************************
// 条件编译
#ifndef CLINE_H
#define CLINE_H
class CLine:public CPoint
{
protected:
double m_dLength;
public:
CLine(double x = 0, double y = 0, double l = 0);
void set(double x, double y, double l);
double getLength();
};
#endif
这些命令的作用是防止头文件重复包含。拿头文件CLine.h为例来稍微描述一下过程:当编译器在源文件(cpp文件)中第一次遇到头包含命令“#include “CLine.h””时,打开头文件CLine.h,准备对其在源文件中进行展开、编译。此时发现宏“CLINE_H”没有被定义,于是先定义这个宏,再将其后的代码进行编译,直到遇到“#endif”命令为止。当编译器在源文件中第二次遇到头包含命令“#include “CLine.h””时,再次打开头文件CLine.h,准备对其在源文件中进行展开、编译。然而此时发现宏“CLINE_H”已经被定义过了,于是后面的代码被跳过,不编译,直接跳至“#endif”命令。这样中间的代码就不会被再次编译了,也就不会出现重复定义的问题。
另外补充一下,除了“#ifndef”和“#endif”这对条件编译命令外,还可以使用其他类似功能的条件编译指令。下面几种方式都可用于避免重复包含:
-
- #ifndef MACRO
- #define MACRO
-
-
-
-
-
- #endif
#ifndef MACRO
#define MACRO
// ……
// 代码
// ……
#endif
-
- #if !define(MACRO)
- #define MACRO
-
-
-
-
-
- #endif
#if !define(MACRO)
#define MACRO
// ……
// 代码
// ……
#endif
#pragma once
// ……
// 代码
// ……
前两种是等价的,后一种中“#pragma once”的意思是:在编译一个源文件时,只对该文件包含(打开)一次。至于它于前两种的区别,不是本文主题所在,这里就不讲了。
步骤三:
删除所有文件(源文件和头文件)中的头包含命令。并在头文件StdAfx.h中包含当前工程所需要的所有头文件。如下:
-
-
-
-
-
-
-
- #ifndef STDAFX_H
- #define STDAFX_H
-
-
- #include <iostream>
- #include <stdlib.h>
- using namespace std;
- #include "CPoint.h"
- #include "CLine.h"
- #include “test.h”
-
- #endif STDAFX_H
//*******************************
//* 头文件:StdAfx.h *
//* 描 述:包含所有头文件 *
//*******************************
// 条件编译
#ifndef STDAFX_H
#define STDAFX_H
// 包含工程所需所有头文件
#include <iostream>
#include <stdlib.h>
using namespace std;
#include "CPoint.h"
#include "CLine.h"
#include “test.h”
#endif STDAFX_H
步骤四:
在所有源文件(cpp文件或者c文件)首部包含头文件StdAfx.h,且仅包含这个头文件。
到此,工程已经可以很好的工作了,而且上面的四个步骤对于C语言和C++,对于其他编译环境(如gcc、g++,不只在vc中)都适用。我们来整体看一下我们修改后的各个文件:
-
-
-
-
-
-
-
- #ifndef CPOINT_H
- #define CPOINT_H
-
- class CPoint
- {
- protected:
- double m_dX;
- double m_dY;
- public:
- CPoint(double x = 0, double y = 0);
- virtual void set(double x, double y);
- double getX();
- double getY();
- };
-
- #endif
//***************************************
//* 头文件:CPoint.h *
//* 描 述:点类CPoint的声明 *
//***************************************
// 条件编译
#ifndef CPOINT_H
#define CPOINT_H
class CPoint
{
protected:
double m_dX;
double m_dY;
public:
CPoint(double x = 0, double y = 0);
virtual void set(double x, double y);
double getX();
double getY();
};
#endif
-
-
-
-
-
-
-
- #ifndef CLINE_H
- #define CLINE_H
-
- class CLine:public CPoint
- {
- protected:
- double m_dLength;
- public:
- CLine(double x = 0, double y = 0, double l = 0);
- void set(double x, double y, double l);
- double getLength();
- };
-
- #endif
//***************************************************************
//* 头文件:CLine.h *
//* 描 述:线类CLine的声明,CLine由CPoint的派生而来。 *
//***************************************************************
// 条件编译
#ifndef CLINE_H
#define CLINE_H
class CLine:public CPoint
{
protected:
double m_dLength;
public:
CLine(double x = 0, double y = 0, double l = 0);
void set(double x, double y, double l);
double getLength();
};
#endif
-
-
-
-
-
-
-
- #ifndef STDAFX_H
- #define STDAFX_H
-
-
- #include <iostream>
- #include <stdlib.h>
- using namespace std;
- #include "CPoint.h"
- #include "CLine.h"
- #include “test.h”
-
- #endif STDAFX_H
//*******************************
//* 头文件:StdAfx.h *
//* 描 述:包含所有头文件 *
//*******************************
// 条件编译
#ifndef STDAFX_H
#define STDAFX_H
// 包含工程所需所有头文件
#include <iostream>
#include <stdlib.h>
using namespace std;
#include "CPoint.h"
#include "CLine.h"
#include “test.h”
#endif STDAFX_H
-
-
-
-
-
-
- #ifndef TEST_H
- #define TEST_H
-
- void test();
-
- #endif
//***************************************
//* 头文件:test.h *
//* 描 述:test.cpp中的函数声明 *
//***************************************
#ifndef TEST_H
#define TEST_H
void test();
#endif
-
-
-
-
-
- #include "StdAfx.h"
-
- int main()
- {
- CLine line;
-
- line.set(1.2, 2.3, 3.4);
- cout << line.getX() << endl;
- cout << line.getY() << endl;
- cout << line.getLength() << endl;
- test();
- system(“pause”);
- return 0;
- }
//*******************************
//* 源文件:main.cpp *
//*******************************
#include "StdAfx.h"
int main()
{
CLine line;
line.set(1.2, 2.3, 3.4);
cout << line.getX() << endl;
cout << line.getY() << endl;
cout << line.getLength() << endl;
test();
system(“pause”);
return 0;
}
-
-
-
-
-
- #include "StdAfx.h"
-
- void test()
- {
-
- CLine line;
-
- line.set(2.4, 1.5, 4.7);
- cout << line.getX() << endl;
- cout << line.getY() << endl;
- cout << line.getLength() << endl;
- }
//*******************************
//* 源文件:test.cpp *
//*******************************
#include "StdAfx.h"
void test()
{
CLine line;
line.set(2.4, 1.5, 4.7);
cout << line.getX() << endl;
cout << line.getY() << endl;
cout << line.getLength() << endl;
}
//*******************************
//* 源文件:StdAfx.cpp *
//*******************************
#include "StdAfx.h"
二、神行太保——预编译头文件
1、剥开StdAfx的神秘面纱
如果你潜意识里感觉有什么东西不太搭调的话,那么你直觉是正确的。到此为止,都看不出源文件StdAfx.cpp有何功用,难道它是多余的?其实不然,它在VC中可以发挥更大的作用,可以使得一个庞大的工程在一次漫长的编译过后,接下来的编译更畅快,大大提高编译效率。不过要发挥它的作用必须借助于VC的环境设置,并不是所有开发环境都支持该功能。
下面是摘用“百度百科”的几段话来说明StaAfx的作用。如果没看明白也没关系,接下来不讲理论,只谈浅显的运用。
“Microsoft C 和 C++ 编译器提供了用于预编译任何 C 或 C++ 代码(包括内联代码)的选项。利用此性能特性,可以编译稳定的代码体,将已编译状态的代码存储在文件中,以及在随后的编译中,将预编译的代码与仍在开发的代码结合起来。由于不需要重新编译稳定代码,因此后面每次编译的速度都要快一些。”
“ VC创建项目时自动创建的预编译头文件,在编译其他文件之前,VC先预编译此文件。头文件stdafx.h引入了项目中需要的一些通用的头文件,比如window.h等,在自己的头文件中包括stdafx.h就包含了那些通用的头文件。
所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。