使用#ifndef时,.h文件被多次添加

时间:2010-04-18 19:53:04

标签: c++ c-preprocessor

我正在尝试使用以下模式。

#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"

3 个答案:

答案 0 :(得分:2)

首先,标题守卫进入文件内部。它使它更容易:

// some_header.h
#ifndef SOME_HEADER_INCLUDED_H
#define SOME_HEADER_INCLUDED_H

// ...

#endif

其次,这些警卫只能保护多个包含 per-translation-unit 。如果您有main.cppfoo.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;