上个星期回学校的时候,刚好碰到一个学弟在写程序,并且刚好碰到一个总编不过去的问题,我看了看,正好是个头文件重复包含问题,问题描述如下: 他在程序中建立了一个global.h的文件,代码如下: #ifndef _GLOBAL_H_ #define _GLOBAL_H_ int a; int b; int c; 然后在其他文件代码中,有多个.cpp文件引用他,编译的时候编译器报变量重复定义。 其实这是个C语言的基本问题,如果学过编译原理的人就很清除问题在哪里。假设上面的头文件global.h,有三个.cpp文件,1.cpp, 2.cpp, 3.cpp都包含了这个头文件。那么在编译的时候分别生成 1.obj, 2.obj, 3.obj。在这三个obj文件中都包含变量a, b, c。那么在链接的时候你让机器怎么去分别三个a变量,三个b变量,三个c变量,那么就只好给你报个错了。 不过,如果是从事Linux或者以前标准C语言开发的人可能会想,我原来编程就是这么编的,怎么就没有报错。对的,有些编译器是具有这种重定义自动检测的,如Linux下C编程。我目前用的编程环境是Visual studio.net 2003。我写了两个小程序测试了一下,一个是标准C程序,如下: head1.h #ifndef _HEADER1_H_#define _HEADER1_H_ void print_1(); #endif head2.h #ifndef _HEADER2_H_#define _HEADER2_H_ void print_2(); #endif global.h #ifndef _GLOBAL_H_#define _GLOBAL_H_ int g_test; #endif head1.c void print_1(){ g_test=1; printf("%d\n",g_test);} head2.c void print_2(){ g_test=2; printf("%d\n",g_test);} main.c void main(){ print_1(); print_2(); } 经过测试,这种方式是对的。 然后,我写了段c++代码,程序代码和上面的一模一样,就是.c文件变成了.cpp文件。结果就报重定义的错误。 由此可见,这个问题是C++新标准。而上述标准C能够编译过,说明这种对重定义的支持是依据编译器的,但是对于编译器来说,不是必须的。所以程序员写程序最好不要用上述代码写,现在一般程序员对这个问题流行的写法是如下: #ifndef _GLOBLE_H #define _GLOBLE_H extern int a; extern int b; extern int c; #endif 然后在其他的某个.cpp文件中定义 int a; int b; int c; 但是这种写法在具有大量的变量时候,容易造成声明的头文件和变量定义的cpp文件中变量的不一致。 下面是我给出一个的解决方法。 定义一个宏,如:MAIN, 在global.h中,加入如下代码: #ifdef MAIN #define EXTERN //定义变量 #else #define EXTERN extern //声明变量 #endif EXTERN int a; EXTERN int b; EXTERN int c; 然后在你的1.cpp , 2.cpp , 3.cpp 中,在其中的一个.cpp中 #define MAIN #include "gloabl.h" 进行定义。这样相当于对gloabl.h中的变量进行定义。 而在其他的cpp中,如需要引用global.h中的变量,则 #include "gloabl.h" 而不需要#define MAIN.或者将#define MAIN定义在#include "gloabl.h"的后面。这样编译的时候就会将gloabl.h中的变量作为声明来看待。 这样即使变量再多,也不会出现头文件和CPP文件中的变量不符。因为所有的变量只需在一个文件中写入。 嘿嘿,完了,不知道有没有说清楚。如果还有疑惑欢迎大家提问交流。

评论