首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在多个cpp中包含相同的头部导致重复的多个定义错误

在多个cpp中包含相同的头部导致重复的多个定义错误
EN

Stack Overflow用户
提问于 2008-10-21 22:27:46
回答 9查看 38.7K关注 0票数 15

因此,无论我做什么,我似乎都无法避免Dev C++由于我在同一项目的多个源代码文件中包含相同的头文件而导致的大量多个定义错误。我强烈希望避免将我所有的源代码转储到一个文件中,并且只包含一次头文件,因为这将使我的文件非常长且难以管理。

本质上,这就是正在发生的事情:

代码语言:javascript
复制
#ifndef _myheader_h
#define _myheader_h

typedef struct MYSTRUCT{
int blah;
int blah2; } MYSTRUCT;

MYSTRUCT Job_Grunt;
MYSTRUCT *Grunt = &Job_Grunt;
MYSTRUCT Job_Uruk;
MYSTRUCT *Uruk = &Job_Grunt;

int Other_data[100];

void load_jobs();

#endif

示例Cpp文件(它们几乎都看起来像这样):

代码语言:javascript
复制
#include "myheader.h"

void load_jobs(){

Grunt->blah = 1;
Grunt->blah2 = 14;

Uruk->blah = 2;
Uruk->blah2 = 15;

return; }

请记住,我有大约5个cpp文件,其中包括这一个头文件,每个文件处理在头文件中找到的不同类型的结构。在这个例子中,只有一个包含几个成员的结构,而在实际的头文件中,大约有4-6个不同的结构,还有更多的成员。我在其中包含的所有文件都遵循与您在此示例中看到的相同的公式。

现在我明白了,头保护只会多次阻止每个单独的cpp文件包含头文件。似乎正在发生的情况是,当编译器读取每个cpp开头的include时,它会重新定义头文件,这会导致它输出一行又一行:

代码语言:javascript
复制
Multiple Definition of Uruk, first defined here  
Multiple Definition of Job_Uruk, first defined here  
Multiple Definition of Grunt, first defined here  
Multiple Definition of Job_Grunt, first defined here  
Multiple Definition of Other_data, first defined here

我将为项目中的几乎每个cpp文件看到一组这样的内容,其中包括头文件。我尝试将struct和struct变量的定义移动到cpp文件中,但是其他cpp文件看不到它们,也无法使用它们,这一点非常重要,因为我需要项目中的所有文件都能够使用这些结构。

但这个问题最令人困惑的部分需要更多的解释:

我在这个项目中设置这些多个文件的方式与我正在使用的书“一个游戏中的编程”一书中的完全相同。我在创建文件时遇到了完全相同的问题,例如书中的项目,它要求同一项目中的多个cpps包含一个头文件。

我可以逐字逐句地把它们打出来,而且我是逐字逐句的……

我会得到项目中每个cpp的一系列MD错误。

如果我从书中附带的CD加载示例项目,它将编译并运行没有问题,尽管文件本身以及项目选项在所有外观上都与我创建的文件相同。

如果我创建了自己的项目文件,并简单地从CD添加示例项目的源文件和头文件,也可以编译和运行这些文件,尽管我找不到它们和我的文件之间的区别。

因此,我尝试制作自己的项目文件,然后创建空白的源文件和头文件并将它们添加到其中,然后通过从CD上的文件中复制和粘贴它们的内容来填充它们(与正常工作的文件相同)。果然,我会得到相同的thing...lines和MD错误消息行。

我完全被弄糊涂了。我已经多次重复了所有这些方法,并且确信我没有输入错误或错误复制代码。预制文件本身似乎有些问题;一些配置设置或我遗漏的其他东西,entirely...that会导致它们正确编译,而我自己制作的文件则不会。

EN

回答 9

Stack Overflow用户

发布于 2008-10-21 22:36:05

由于您在头文件中声明了这些变量,并在每个C++文件中包含了头文件,因此每个C++文件都有其自己的副本。

通常的解决方法是不在头文件中声明任何变量。相反,可以在单个C++文件中声明它们,并在可能需要它们的所有其他文件中将它们声明为extern

另一种我以前处理过的方式,有些人可能会觉得不愉快……在头文件中声明它们,如下所示:

代码语言:javascript
复制
#ifdef MAINFILE
    #define EXTERN
#else
    #define EXTERN extern
#endif

EXTERN MYSTRUCT Job_Grunt;
EXTERN MYSTRUCT *Grunt = &Job_Grunt;
EXTERN MYSTRUCT Job_Uruk;
EXTERN MYSTRUCT *Uruk = &Job_Uruk;

然后,在其中一个C++文件中,添加一个...

代码语言:javascript
复制
#define MAINFILE

...before你的#include线路。这将解决所有问题,并且(在我个人看来)比不得不在每个文件中重新声明所有变量要好得多。

当然,真正的解决方案是根本不使用全局变量,但当您刚刚开始时,这是很难实现的。

票数 25
EN

Stack Overflow用户

发布于 2008-10-21 22:41:13

定义变量时,编译器会为该变量预留内存。通过在头文件中定义一个变量,并将该文件包含到所有源文件中,您可以在多个文件中定义相同的变量。

将关键字extern放在变量定义之前将告诉编译器此变量已在某处定义,您只是声明(即命名)此变量,以便其他文件可以使用它。

因此,在您的头文件中,您应该通过添加extern关键字来进行所有定义的转发声明。

代码语言:javascript
复制
extern MYSTRUCT Job_Grunt;
extern MYSTRUCT *Grunt;
extern MYSTRUCT Job_Uruk;
extern MYSTRUCT *Uruk;

extern int Other_data[100];

然后在的一个(且只有一个)源文件中,正常定义变量:

代码语言:javascript
复制
MYSTRUCT Job_Grunt;
MYSTRUCT *Grunt = &Job_Grunt;
MYSTRUCT Job_Uruk;
MYSTRUCT *Uruk = &Job_Grunt;

int Other_data[100];
票数 13
EN

Stack Overflow用户

发布于 2008-10-22 01:21:38

虽然大多数其他答案是正确的,为什么你会看到多个定义,但术语是不精确的。理解声明与定义是解决问题的关键。

声明声明项的存在,但不会导致实例化。因此,外部语句是声明,而不是定义。

定义创建已定义项的实例。因此,如果在头文件中有一个定义,它将在每个.cpp文件中实例化,从而产生多个定义。定义也是声明-例如,如果项的范围被限制到一个.cpp文件,则不需要单独的声明。

注意:这里使用的实例化这个词实际上只适用于数据项。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/223771

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档