预编译头文件是什么意思??为什么在stdafx.h中可以定义变量???

RickeyLau 2003-03-19 10:48:43
而stdafx.h被很多cpp嵌入,为什么不会出现重复定义呢??
...全文
509 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
solar 2003-03-21
  • 打赏
  • 举报
回复
没错,是vc++对预编译头文件作了只包含一次的处理;我用gcc作了同样的实验,会发生重复定义错误
zhdleo 2003-03-20
  • 打赏
  • 举报
回复
stdafx.h被很多cpp嵌入 为什么会想到重复定义??

那我问:一个类,被你在其他多个类中 定义,引用,算不算重复定义:)

netease 2003-03-20
  • 打赏
  • 举报
回复
stdafx.h里面好像是有#pragma once吧
solar 2003-03-20
  • 打赏
  • 举报
回复
stdafx.h是vc默认的预编译头文件,也就是说只编译一次,以后每次只是使用相应的.pch文件,你在stdafx.h定义的对象肯定编译到.pch中了,而.pch应该是一种特殊的.obj文件,所以不会发生重复定义的现象。vc编译器可能对于预编译头文件作了只包含一次的处理。你也可以指定其他的头文件作为预编译头文件,但是好像每个工程只能有一个预编译头文件
RickeyLau 2003-03-20
  • 打赏
  • 举报
回复
to solar(这里空间太小!!!) :你还是没有理解我说的问题

你用vc向导建一个MFC exe,在CxxxDoc.h 的末尾添加上int x; 然后build ,肯定出错,
因为在CxxxDoc.cpp, CxxxView.cpp 都inclule了CxxxDoc.h,那么这这两文件中就分别有x的定义,那么链接当然出错了。

但是如果你在stdafx.h的末尾添加上int x; 那就不会出错,
CxxxDoc.cpp,CxxxView.cpp也include了stdafx.h呀?
为什么vc的链接器只认其中一个定义?而将其余的定义作为声明呢?就像在对x使用了
__declspec( selectany ) 修饰一样
rivershan 2003-03-20
  • 打赏
  • 举报
回复
所谓的预编译头就是把一个工程中的某一部分代码,预先编译好放在一个文件里(通常是以.pch为扩展名的),这个文件就称为预编译头文件。这些预先编译好的代码可以是任何的C/C++代码,但是必须是稳定的,在工程开发的过程中不会被经常改变。如果这些代码被修改,则需要重新编译生成预编译头文件。生成预编译头文件很耗时间。预编译头文件通常很大,通常有6-7M大。应该及时清理那些没有用的预编译头文件。

编译器是以文件为单位编译的,一个文件经过修改后,会重新编译整个文件,当然在这个文件里包含的所有头文件中的东西如宏等,都要重新处理一遍。VC的预编译头文件保存的正是这部分信息,以避免每次都要重新处理这些头文件。
预编译头的作用:

要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件)

VC工程里的 StdAfx.h这个文件就是这样一个头文件,它是可以任意命名的,只不过VC的默认命名为StdAfx.h。我们来考察一个典型的由AppWizard生成的MFC Dialog Based 程序的预编译头文件。这个头文件里的内容一般如下:

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__AC2D3C17_0808_4AB5_B6B7_CABF7808B0B7__INCLUDED_)
#define AFX_STDAFX_H__AC2D3C17_0808_4AB5_B6B7_CABF7808B0B7__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__AC2D3C17_0808_4AB5_B6B7_CABF7808B0B7__INCLUDED_)

这里面包含的头文件正是使用MFC的必须包含的头文件,当然我们不太可能在我们的工程中修改这些头文件的,所以说它们是稳定的。并且,StdAfx.h的位置必须在其它的包含的头文件之前,否则会出大量错误。

对于VC来说,单独一个头文件是不能编译的。所以我们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件里只有一句代码就是:#include “Stdafx.h”。其作用仅仅就是要它具有.cpp的扩展名而能够被编译而已。可以用 /Yc编译器选项来指定某一个文件来生成一个相关的预编译头文件,通过 /Fp编译器选项来指定生成的pch文件的名字,通过 /Yu编译器选项来指定整个工程的相关预编译头文件。在Project ->Setting->C/C++ 里,通过Category中的Precompiled Header可以进行这些设定和调整。
solar 2003-03-20
  • 打赏
  • 举报
回复
在上述3中方法中,gcc推荐使用第一种方法,另外二中可移植性较差
solar 2003-03-20
  • 打赏
  • 举报
回复
gcc中还可以这样也能保证.h文件只包含一次

#import "myheader.h"
xhncmecx 2003-03-20
  • 打赏
  • 举报
回复
mark
solar 2003-03-20
  • 打赏
  • 举报
回复
用这种形式可以避免stdafx.h被包含多次
#ifndef __STDAFX_H_INCLUDED
#define __STDAFX_H_INCLUDED

...

#endif

这样也可以

#pragma once

SatanLi1982 2003-03-20
  • 打赏
  • 举报
回复
一切都是#ifdef和#define #endif
等宏的作用
比如:
#ifndef HELLO
#define HELLO
int hello=5;
#endif
这样hello就不会被重复定义。
Free_Man 2003-03-20
  • 打赏
  • 举报
回复
变量可以定义在任何.cpp/.c/.h文件中.

变量定义在stdafx.h中,则说明任何包含stdafx.h文件的的文件中可以使用该变量
RickeyLau 2003-03-20
  • 打赏
  • 举报
回复
没有人注意过这个问题?
RickeyLau 2003-03-20
  • 打赏
  • 举报
回复
你们没有明白我的意思,
举个例子,如果你在一个头文件A.h中定义(注意是“定义”不是“声明”)了一个变量 int x; 然后你在B.cpp,C.cpp,D.cpp等多个cpp文件中包含了A.h(inlucde"A.h"),那么就会出现x重复定义变量的错误,
但是如果你把x的定义放在stdafx.h中,那么就不会出现错误,这是为什么?
stdafx.h与一般的头文件有什么区别??
dszch 2003-03-20
  • 打赏
  • 举报
回复
一个编译系统的好坏,其中一个重要的指标是编译的速度!
stdafx.h中包含以下一些语句,其主要目的是提高编译的速度,节省编译时间.
比如下面三句语句的意思是:
#if !defined //如果没有定义下面这一句(AFX_TEXTPROGRESSCTRL_H__4C78DBBE_EFB6_11D1_AB14_203E25000000__INCLUDED_)

#define //就定义这一句
AFX_TEXTPROGRESSCTRL_H__4C78DBBE_EFB6_11D1_AB14_203E25000000__INCLUDED_
//否则结束,即如果定义过了,就结束
#endif//最后应该还有这一句,

这样做的主要目的是,节省你第二次编译的时间,你应该有感觉,在调试一个VC程序时,第一次编译的时间比较长,而第二次编译时间就很短了!就是上面这些语句的作用

另外,在头文件的这几句
#if _MSC_VER >= 1000
#pragma once
#endif
这三句是一组pragma条件预编译语句,要求当进行编译时,本文件只能打开一次
#if _MSC_VER >= 1000 中的 _MSC_VER 是微软C++编译器提供的若干预定义宏的一种,用它表示编译的版本,Mircsoft Visual C++6.0被定义为1200,所以满足 _MSC_VER >= 1000的条件.

在VC++ 6.0的帮助文件中指出,pragma可以以条件语句的形式提供一种新的预处理功能,向编译器提供某些规定的编程信息.C和C++认可许多这样的语句
#pragma *;比如#pragma warning等,
语句#pragma once 是其中的一种,它告诉编译器,项目进行编译时只能将本文件包含(打开)一次。

再一句 #define VC_EXTRALEAN 是一个定义语句,它的功能是删去头文件中那些用不着的资料,以减少头文件的大小,提高编译速度。

这样可以提高编译的速度!

16,550

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧