头文件定义全局变量的几个问题

工程中有三个文件如下: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。

原文地址:https://www.cnblogs.com/phyking/p/4456667.html