多个定义的符号 C++ 错误
Posted
技术标签:
【中文标题】多个定义的符号 C++ 错误【英文标题】:Multiple Defined Symbols C++ error 【发布时间】:2011-07-19 05:31:54 【问题描述】:我以为ifndef something #define something body #endif
解决了这个错误,所以我不确定为什么会这样。
//Library.h
#ifndef __LIBRARY__
#define __LIBRARY__
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdlib>
//file includes
#include "Globals.h"
using namespace std;
#endif //__LIBRARY__
--
//globals.h
//global variables
#ifndef __GLOBAL__
#define __GLOBAL__
#include <vector>
#include <iostream>
#include <string>
//prototypes
bool Poglathon(std::vector<std::string>& text);
void NPCTalk(std::string const& speaker,std::vector<std::string> const& text);
void wait(double seconds);
//player stats
std::string name;
double str; //strength
double wis; //wisdom
double ref; //reflex
double hp; //health points
double i; //initiative
double inte; //intelligence
double c; //courage
int gold; //gold
int xp; //experience
int ap; //armour points
int wd; //weapon damage
int lvl; //level
int sp; //skill points
#endif //__GLOBAL__
还有另外两个包含“Library.h”的 cpp 文件。
【问题讨论】:
不相关:带有双下划线的标识符是reserved for the compiler。 多重定义符号是哪一个? 不相关:需要对其名称进行注释的标识符可能没有正确命名。 【参考方案1】:问题在于,在您的 globals.h 头文件中,您声明了一组默认情况下具有外部链接的变量:即所有全局变量!
当您在头文件中创建函数原型时,您是在声明一个函数,而不是定义它。对同一个函数进行多次声明是完全合法的,这就是为什么如果几个不同的文件都#include
同一个头文件并声明同一个函数是完全可以的。另一方面,如果您在头文件中有全局变量,那么您就是在定义这些变量。变量在 C++ 中只能定义一次(这称为单一定义规则),如果多个文件定义相同的变量或函数,则会导致链接器错误,因为链接器不知道哪个要使用的版本。顺便说一句,这就是您不使用 #include
.cpp 文件的原因,因为如果这样做,您将乘以定义该标头导出的所有函数。
要解决此问题,您需要在标题中使用 extern
关键字将这些变量 definitions 更改为变量 declarations:
//player stats
extern std::string name;
extern double str; //strength
extern double wis; //wisdom
extern double ref; //reflex
extern double hp; //health points
extern double i; //initiative
extern double inte; //intelligence
extern double c; //courage
extern int gold; //gold
extern int xp; //experience
extern int ap; //armour points
extern int wd; //weapon damage
extern int lvl; //level
extern int sp; //skill points
这将允许任意数量的文件到#include
这个头文件,因为它们实际上都没有定义变量;他们只是在声明变量将存在于某处。然后,您应该创建一个新的 .cpp 文件,可能是 globals.cpp,它实际上定义了变量:
#include "globals.h"
std::string name;
double str; //strength
double wis; //wisdom
double ref; //reflex
double hp; //health points
double i; //initiative
double inte; //intelligence
double c; //courage
int gold; //gold
int xp; //experience
int ap; //armour points
int wd; //weapon damage
int lvl; //level
int sp; //skill points
这些是变量的实际定义,由于它们只存在于一个位置 (globals.cpp),因此您不会再收到任何链接器错误。
希望这会有所帮助!
【讨论】:
所以包含守卫根本没有发挥作用,因为每个编译单元仍然只包含一次标头?我说对了吗? 完全正确。包含保护可以防止您在一个文件中包含相同代码的两个副本,但不要说当您尝试将多个包含标题的文件链接在一起时会发生什么。【参考方案2】:你的 C++ 代码有很多问题
切勿在触发多个符号的标头中直接声明全局变量,因为它们将出现在每个编译单元中(使用它们的 ~cpp 文件)一种解决方案是将它们设为外部,但我强烈建议您使用而是持有这些参数的类或结构。除此之外:
切勿在全局范围内的头文件中执行“使用命名空间 xxx”。您将强制使用标头的每个人都将符号拉到全局命名空间内。 它不遵循 C++ 语义,看起来更像 C(我真的会将所有玩家统计数据封装在一个同名的类中!)【讨论】:
+1 用于 OP 代码的许多问题,并且永远不要在标头中使用命名空间 std。 好的,我可能会把它们放在一个班级里。以上是关于多个定义的符号 C++ 错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 MatLab dll 时出现 C++ 错误:找到一个或多个多重定义符号