头文件定义全局变量的几个问题
工程中有三个文件如下:main.cpp,Calc1.h和Calc1.cpp.内容如下:
//****************mian文件的内容******************************//
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Calc1.h"
#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
double temp;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent*Owner)
:TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcallTForm1::Button1Click(TObject *Sender)
{
change();
Label2->Caption=FloatToStr(a);
Label3->Caption=FloatToStr(b);
temp=chu();
Label1->Caption=FloatToStr(temp);
Label4->Caption=FloatToStr(display());
}
//---------------------------------------------------------------------------
//本文地址:http://hi.baidu.com/phykingpeng/blog/item/7dd099226168c3844723e86e.html
//************************Calc1.h的内容*******************************//
/*#ifndef __CALC1__H__
#define __CALC1__H__ */
double a,b;
double chu();//double,double);
void change();
double display();
//#endif // __TEMP__H__
//************************Calc1.cpp的内容*******************************//
#include "main.h"
#include "Calc1.h"
//extern double a,b;
/*
这里用#include "Calc1.h"后第一次编译会报错(有warning,
[BCC32 Warning] Calc1.h(3): W8058 Cannotcreate pre-compiled header: initialized data in header),之后编译有下面这个警告
[ILINK32 Warning] Warning: Public symbol'_a' defined in both module DEBUG\CALC1.OBJ and \DEBUG\UNIT1.OBJ
但是访问的值感觉是二个不同的值(表面上同名实际上是两个值)
*/
void change()
{
a=StrToFloat(Form1->Edit1->Text);
b=StrToFloat(Form1->Edit2->Text);
}
double chu()//double i,double j)
{
return(b/a);//i/j;
}
double display()
{
returna;
}
分析:Calc1.h无论用不用宏定义,编译的时候都会有[ILINK32 Warning] Warning: Public symbol '_a' defined in both module..\RAD STUDIO\PROJECTS\多文件\DEBUG\MAIN.OBJ and ..\RAD STUDIO\PROJECTS\多文件\DEBUG\CALC1.OBJ这个警告。原因是工程中含有两个CPP文件,编译器分别讲Calc1.h插入到main.cpp和Calc.cpp对应的位子,编译成对应的两个.OBJ文件(MAIN.OBJ和CALC1.OBJ)。这样在link的时候,两个OBJ中就分别有一份a,b的定义,连接的时候就有重复定义的warning。实际运行的时候Calc1.cpp中三个函数调用的是自己文件中定义的a,b。main.cpp中调用的是全局的a,b(Label2->Caption=FloatToStr(a);)这里相当于有个全局的a,b和一个局部的a,b。所以同样使用两个参数得出的结果却不一样lable2和Label3为0(全局),Label4为edit中的a值(Edit1->Text);)(局部)label1输出除法为edit控件保存到局部变量中的计算值。
总结:1. #include中定义全局变量用宏定义,就像上面Calc1.h注释掉的那样。但是引用的时候包含只能一次,其他文件中应该以extern声明,像Calc1.cpp中注释掉的那样//extern double a,b;。不要用#include "Calc1.h"包含头文件,否则就会出现上面的局部和全局变量重名,访问的不一致的问题。有说法是最好不要再头文件中定义变量,有一定的道理。
2.注意编译的过程:#include是完全复制被包含的文件到这一行,工程中的多个CPP文件分别编译成不同的OBJ,再连接成exe.
3.宏定义是用来避免重复包含的,比如多个文件有重叠包含关系。有全局变量的头文件只被主程序包含,其他文件中用extern。