C++中两个文件读取一个.h时多个多重定义错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中两个文件读取一个.h时多个多重定义错误相关的知识,希望对你有一定的参考价值。

我有个tools.h文件 里面创建了全局变量Map

main里我用memset给map设初值

然后tools里的updateMap函数用来刷新Map

报错说
错误 1 error LNK2005: "char (* Map)[40]" (?Map@@3PAY0CI@DA) 已经在 glutt.obj 中定义 C:\Users\User\Documents\GitHub\C++\glutt\glutt\tools.obj glutt

但是我在tools.h里定义了
#ifndef _TOOL_H_
#define _TOOL_H_

所以第二次尝试导入不是会直接跳过吗? 为啥还会重定义

从昨晚到现在查了很多东西,但结果却超级简单:
首先#include在编译时会被预处理器将.h中的所有内容拷贝到当前文件中, 如果.h中还include了别的.h, 则递归拷贝;
如果.h文件中没有头文件保护,即#ifndef ... #define ... #endif则如果某文件include 1.h和 3.h, 而1.h也#include了3.h, 则会有完全相同的两份3.h中的代码, 这样就直接报错了; 但加入了头文件保护后就可以保证在单一文件中只会编译一遍3.h的代码;
所以到目前为止如果加入了头文件保护,在单一文件中不会有重声明(定义),编译可以通过,生成各个.o文件了, 头文件中定义的变量都定义并分配了空间,就你的问题而言,tool.o中有Map, 同时main.o中也有Map;
然后就是链接了,此时会将各.o中的全局符号加入全局符号表中,如果.o中有相同的全局变量则会报重定义, 即tool.o和main.o中的Map冲突了。

总结下:头文件保护只是保证在 单一文件中不会重复include, 但不保证在不同文件中重复include。

解决办法为在.h中只声明变量: extern map Map; 而在tool.cpp中定义: map Map;

多谢问题哈,终于搞清楚了这个问题!
参考技术A #ifndef _TOOL_H_
#define _TOOL_H_
// 定义内容嵌入这里
#endif // 条件结束标志 不要漏了追问

没漏 不然vs会检测到的

追答

那么 括的位置 是否正确 -- 语法,语意。
还有,主函数前面 要有 updateMap() 函数的原型声明。

visual C++ typedef struct 多重定义符号问题

【中文标题】visual C++ typedef struct 多重定义符号问题【英文标题】:visual C++ typdef struct multiple defined symbols problems 【发布时间】:2011-09-07 07:48:38 【问题描述】:

在 Visual C++ 中,我遇到了“致命错误 LNK1169:找到一个或多个多重定义的符号”,下面的代码,如果我想在两个源中包含两个头文件以供其他函数使用,我该如何解决这个问题?

main.cpp
========
#include main.h
#include sub.h

sub.cpp
========
#include main.h
#include sub.h

sub.h
=========

typedef struct
      char colour;
      char name;
person;

person ssss =  red, ali;

【问题讨论】:

【参考方案1】:

你的问题是你在头文件中定义了一个变量:

person ssss =  red, ali ;

一个在 main.cpp 中实例化,一个在 sub.cpp 中实例化。你最好写一个:

extern person ssss;

在头文件中,然后在其中一个源文件中定义一次变量。这将使两个源文件都知道它存在,并且两者都将引用同一个变量,假设这是您想要的。就像其他答案所建议的那样,我也肯定会建议使用 header guards,虽然您在此示例中并不特别需要它们,但这是一种很好的做法,从长远来看可以让您头疼。

【讨论】:

【参考方案2】:

在两个源文件中都包含 typedef 应该不是问题。问题是 ssss 的声明通过 sub.h 出现在两个文件中。将其放入源文件之一并在标头中将其声明为外部以解决此问题。请注意,您有一个链接错误,而不是编译错误——这是因为在多个目标文件中找到了该符号。

【讨论】:

【参考方案3】:

你应该在你的头文件中添加包含保护,以防止同一个头文件被多次包含。

#ifndef SUB_H
#define SUB_H


//end of file
#endif

另外一件事,你为什么要在你的 sub.cpp 中包含 main.h?这似乎是错误的。

【讨论】:

【参考方案4】:

在sub.h中,在文件顶部插入以下内容;

#pragma once

【讨论】:

【参考方案5】:
person ssss =  red, ali;

sssssub.cppmain.cpp 中被实例化一次,因为sub.h 包含在任何一个文件中。实例化通常在源文件中而不是头文件中。现在,当您访问对象ssss 成员变量时,链接器无法访问哪个对象,因为它们都共享相同的范围。

解决方案是拥有一个全局实例(如果这是您想要的),并且可以通过外部链接跨不同文件进行访问。

main.cpp
========
#include main.h       // What is main.h required for ?
#include sub.h

extern person ssss;

sub.cpp
========
#include main.h       //  ?!?!
#include sub.h

person ssss =  red, ali;

sub.h
=========

typedef struct
      char colour;
      char name;
person;

【讨论】:

以上是关于C++中两个文件读取一个.h时多个多重定义错误的主要内容,如果未能解决你的问题,请参考以下文章

C++找到一个或多个多重定义的符号

visual C++ typedef struct 多重定义符号问题

C++ 链接错误与 Linux 上的多个定义

c++中的多重定义错误

链接阶段的多重定义错误

使用 MatLab dll 时出现 C++ 错误:找到一个或多个多重定义符号