[英]How to avoid linker error
内部General.h
#ifndef GENERAL
#define GENERAL
namespace counternamespace{
int upperbound;
int lowerbound;
}
#endif
Inside Analyzer.h
#ifndef ANALYZER
#define ANALYZER
#include"General.h"
class Analyzer
{
public :
int var ;
int func();
};
#endif
内部Test.h
#ifndef TEST
#define TEST
#include"Analyzer.h" //Error
class Test2
{
public:
Test2(void);
public:
~Test2(void);
};
#endif
在上面的代码中,当我没有在Test.h
添加Analyzer时,一切正常。 但是添加后显示以下链接器错误。
1>Test2.obj : error LNK2005: "int counternamespace::lowerbound" (?lowerbound@counternamespace@@3HA) already defined in Analyzer.obj
2>Test2.obj : error LNK2005: "int counternamespace::upperbound" (?upperbound@counternamespace@@3HA) already defined in Analyzer.obj
我添加了#ifndef
/ #endif
。 那我在哪里做错了? 有人可以让我知道吗?
是的,阿洛克说的没错。 您大概拥有Analyser.cpp和Test2.cpp,它们都是不同的编译单元。 你打电话时
g++ Analyser.cpp Test2.cpp
编译器实际上分别制作了Analyser.obj和Test2.obj并将它们链接在一起。 当编译器尝试将Analyser.obj和Test2.obj链接在一起时,它意识到Test2.obj中的两个变量也存在于Analyser.obj中。
你#define
指令不工作,因为它们只存在于一个单一的编译单元,所以general.h中既在Analyser.obj和Test2.obj包括在内。
为避免此类重复, 解决方案将函数包装您的名称空间变量 。 它是这样的:
内部General.h
#ifndef GENERAL
#define GENERAL
namespace counternamespace{
int& upperbound();
int& lowerbound();
}
#endif
在General.cpp内部
#include "General.h"
namespace counternamespace{
int& upperbound(){static int local; return local;}
int& lowerbound(){static int local; return local;}
}
所以你现在可以说
counternamespace::upperbound()=3;
counternamespace::lowerbound()=1;
它的含义与您所说的相同
counternamespace::upperbound = 3;
counternamespace::lowerbound = 1;
不用担心,编译器将优化函数调用,因此也没有开销。
您不应在头文件中定义任何变量。
当您在其他文件中包含头文件时,将在每个转换单元中创建变量的副本,从而违反了一个定义规则,并导致链接错误。
Inside General.h
#ifndef GENERAL
#define GENERAL
namespace counternamespace{
extern int upperbound;
extern int lowerbound;
}
#endif
Inside General.cpp
#include"General.h"
using namespace counternamespace ;
int counternamepace::upperbound = 12;
int counternamepace::lowerbound = 12;
然后做任何需要的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.