文件结构如下: main.h ,main.cpp, ddraw.h, ddraw.cpp 大致问题如下,在main.h中定义了全局变量,然后在main.cpp以及ddraw.cpp中都要使用到它,所以都包含了此头文件,结果 导致错误: ddraw.obj : error LNK2005: xxxx already defined in main.obj Debug/S.exe : fatal error LNK1169: one or more multiply defined symbols found Error executing link.exe. 表示重复定义了。 一时也没有弄清楚编译头绪,关键在于,全局变量(以下称为global)仅仅就定义了一次,而别的函数只是对于该 头文件进行了引用。 网上查找资料,最通俗的和最深奥的莫过于以下两张帖子: http://topic.csdn.net/t/20050525/17/4035191.html http://blog.csdn.net/xcntime/archive/2009/04/25/4122982.aspx 不过都没有说到我发生的问题的实质上,由于头文件都加入了预编译命令 pragma once (等价于ifndef……define……endif这两个没有去边,一个是宏,另外一个是预编译命令) 然而,解决问题的方法倒是比较容易: 方法1、将global的变量定义写在cpp中,将 extern type global 写在头文件中,其他需要引用到该变量的文件包含该头文件即可(无需再次声明extern)则此时,无论其他文件如何包含都不会出现问题xxxx already defined 为什么呢? 原因在于,在编译阶段,如果系统遇到关键字extern,会把该变量用作声明(声明是不会形成实体的),extern表明:变量global已经在项目中 被定义到了,只要在各个文件中查找便行了。此时,包含该头文件的各个文件生成的obj中,不会实例化变量global(也就是开辟存储空间),所以,global真正 被实例化的时候只有在cpp中自己唯一一次被定义的时候,因为编译该变量的cpp并没有被引用的文件包含,所以,实例只会生成一次,故而不会出现重复定义的错误。 方法2: 将global的定义写在h文件中(但必须通过相应的cpp文件将此头文件包括并生成相应obj),其他需要引用该变量的文件直接说明 extern type global,但是! 绝对不能include 该头文件。 原因,刚刚说了,使用extern关键字时候,编译器不会为相应对象生成实例,所以在相应obj中中找不到global的实例,因为global只在h文件中定义了 ,也就是只会在包含h文件的obj中实例化一次,其他地方引用的话会通过extern关键字找到这个位置,所以可行。 ****小贴士,在同一个项目中,extern关键字声明的变量或者函数,并不需要inlcude该项目下相应的头文件,因为一旦extern所修饰的函数和变量被定义过后,则该符号必然是唯一的,则并不需要指定出在那个文件中出现过它的定义。 那么,回到刚刚问题的最开始,为什么会出现error LNK2005: xxxx already defined in main.obj呢? 头文件中定义了该变量,并且其他所有需要引用到该变量的文件都include了该头文件,所以,每当生成各个相应的obj对象的时候, 该头文件中定义的global都会试图生成一次实例,然后,在编译器检查的时候,一旦发现该变量已经被定义过一次,当另外包含该头文件的对象需要再次定义生成实例时候,就会报出重复定义的错误。 注意,定义和声明的区别 这里需要的是“声明”,不是“定义”!根据C++标准的规定,一个变量是声明,必须同时满足两个条件,否则就是定义: (1)声明必须使用extern关键字;(2)不能给变量赋初值 所以,下面的是声明: extern int a; 下面的是定义 int a; int a = 0; extern int a =0;
全局变量 若有所思
最新推荐文章于 2022-02-25 21:57:21 发布