我正在尝试使用以下模式。
#ifndef TRACER_H
#include "Tracer.h"
#endif
这个语句被添加到代码中的每个文件中,以便tracer.h只添加一次。 我仍然收到一个说多个对象的错误。
Tracer.h也包含
#ifndef TRACER_H
#define TRACER_H
这是错误; 我曾经尝试过一次pragma:
1>Generating Code...
1>Linking...
1>LINK : \\stu05-fsrv.ad.syr.edu\akbhat$\Visual Studio 2008\Projects\Project3\Debug\Project3.exe not found or not built by the last incremental link; performing full link
1>SemiExpression.obj : error LNK2005: "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class tracer &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAVtracer@@@Z) already defined in main.obj
1>SemiExpression.obj : error LNK2005: "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > tracer::log" (?log@tracer@@0V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in main.obj
1>Tokenizer.obj : error LNK2005: "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class tracer &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAVtracer@@@Z) already defined in main.obj
1>Tokenizer.obj : error LNK2005: "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > tracer::log" (?log@tracer@@0V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in main.obj
1>\\stu05-fsrv.ad.syr.edu\akbhat$\Visual Studio 2008\Projects\Project3\Debug\Project3.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Build log was saved at "file://\\stu05-fsrv.ad.syr.edu\akbhat$\Visual Studio 2008\Projects\Project3\Project3\Debug\BuildLog.htm"
答案 0 :(得分:2)
首先,标题守卫进入文件内部。它使它更容易:
// some_header.h
#ifndef SOME_HEADER_INCLUDED_H
#define SOME_HEADER_INCLUDED_H
// ...
#endif
其次,这些警卫只能保护多个包含 per-translation-unit 。如果您有main.cpp
和foo.cpp
,并且每个都包含:
#include "some_header.h"
#include "some_header.h" // again
// ...
包含警戒之间的内容只包含一次每单位,但将被定义两次,每个单位一个。
当链接时间到来时,您将获得多重定义错误。您需要在一个源文件中定义这些静态变量,并且只在标题中声明它。
答案 1 :(得分:0)
也许您想了解include guards。他们应该提供你想要的东西。它们是您案件的一个众所周知的标准模式 根据您的编译器,#pragma once也可能很有趣。也许你在这里阅读了pragma vs. guard(关于SO的问题还有很多好的问题)。
答案 2 :(得分:0)
我认为您忘记在#endif
之后将#ifdef
放入您的包含警戒中。只需在头文件中使用此模式:
#ifndef HEADERNAME_H
#define HEADERNAME_H
/* code */
#endif
此外,您可能在头文件中声明对象实例,最终会在所有源文件中复制并导致链接错误。我需要看一些代码来查看确切问题的位置,但是如果你在头文件中说这个:
Foo myInstance;
您将收到链接器错误,因为符号myInstance引用多个实例(每个包含它的.cpp文件一个)而不是一个。相反,将上面的行放在.cpp
文件中,并将其放在标题中:
extern Foo myInstance;