При использовании #ifndef файл .h добавляется несколько раз - PullRequest
0 голосов
/ 18 апреля 2010

Я пытаюсь использовать следующий шаблон.

#ifndef TRACER_H
#include "Tracer.h"
#endif

Это утверждение добавляется в каждый файл кода, так что tracer.h добавляется только один раз. Тем не менее я получаю сообщение об ошибке, говоря несколько объектов.

Также Tracer.h содержит

#ifndef TRACER_H
#define TRACER_H

Вот ошибка; я тоже однажды попробовал прагму:

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 ]

2 голосов
/ 19 апреля 2010

Во-первых, охранники заголовков попадают внутрь файла. Это делает это намного проще:

// some_header.h
#ifndef SOME_HEADER_INCLUDED_H
#define SOME_HEADER_INCLUDED_H

// ...

#endif

Во-вторых, эти охранники защищают только от нескольких включений за единицу перевода . Если у вас есть main.cpp и foo.cpp, и каждый из них содержит:

#include "some_header.h"
#include "some_header.h" // again

// ...

Содержимое между включенными охранниками будет включено только один раз на единицу , но будет определено дважды, по одному на каждую единицу.

Когда наступит время ссылки, вы получите ошибки с несколькими определениями. Вам нужно, чтобы эти статические переменные были определены в одном исходном файле, и объявлять их только в заголовке.

0 голосов
/ 19 апреля 2010

Я думаю, что вы забыли поставить #endif после #ifdef в вашем включенном охраннике. Просто используйте этот шаблон в ваших заголовочных файлах:

#ifndef HEADERNAME_H
#define HEADERNAME_H

/* code */

#endif

Кроме того, вы можете объявлять экземпляры объектов в заголовочных файлах, которые в итоге дублируются во всех ваших исходных файлах и приводят к ошибкам компоновки. Мне нужно увидеть еще немного кода, чтобы увидеть, где именно проблема, но если вы скажете это в заголовочном файле:

Foo myInstance;

Вы получите ошибки компоновщика, потому что символ myInstance относится к нескольким экземплярам (по одному для каждого файла .cpp, который включает его) вместо одного. Вместо этого поместите указанную выше строку в файл .cpp и поместите в заголовок:

extern Foo myInstance;
0 голосов
/ 18 апреля 2010

Может быть, вы хотите прочитать о включая охранников . Они должны предоставить то, что вы ищете. И это хорошо известный стандартный шаблон для вашего случая.
В зависимости от вашего компилятора прагма # один раз тоже может быть интересной. И, может быть, вы читаете прагма против охранника здесь, на SO (есть гораздо больше хороших вопросов об обоих на SO).

...