2015-02-22 3 views
0

Я продолжаю получать эту ссылку на Visual C++ 2010 LNK2005, говоря, что у меня есть несколько определений двух функций, которые содержатся в «Error.h». (Заголовок я сделал для отображения ошибок)Ошибка ссылки на C++ .. недействительна?

Мой проект так:

BaseImage.h 
BaseImage.cpp --> includes BaseImage.h , Error.h 
PNGImage.h --> includes BaseImage.h 
PNGImage.cpp --> includes PNGImage.h , Error.h 
main.cpp --> includes PNGImage.h 

И, конечно же, error.h:

/* 
Optional macros: 
AE_EXIT_AT_ERROR 
*/ 
#pragma once 
#include <stdexcept> 

void aeError(const char *str, int code=1) 
{ 
    throw std::runtime_error(str); 
    #ifdef AE_EXIT_AT_ERROR 
    std::exit(code); 
    #endif 
} 

void aeAssert(bool b, const char *failStr = "assertion failed") 
{ 
    if(!b) 
     aeError(failStr); 
} 

У меня есть #pragma once в каждом заголовке файл, и я попробовал добавить include guard для Error.h.

Вот результат компиляции:

1>PNGImage.obj : error LNK2005: "void __cdecl aeError(char const *,int)" ([email protected]@[email protected]) already defined in BaseImage.obj 
1>PNGImage.obj : error LNK2005: "void __cdecl aeAssert(bool,char const *)" ([email protected]@[email protected]) already defined in BaseImage.obj 
1>C:\...\Project.exe : fatal error LNK1169: one or more multiply defined symbols found 

Может ли это быть ошибка?

ответ

2

Когда вы определяете функции в файле .h, делайте их inline. В противном случае определения функций являются частью объектного кода всех файлов .cpp, которые #include, с внешней связью.

inline void aeError(const char *str, int code=1) 
{ 
    throw std::runtime_error(str); 
    #ifdef AE_EXIT_AT_ERROR 
    std::exit(code); 
    #endif 
} 

inline void aeAssert(bool b, const char *failStr = "assertion failed") 
{ 
    if(!b) 
     aeError(failStr); 
} 

Другой вариант для вас, чтобы объявить функции в файле .h и определить их точно в одном .cpp файле.

заголовочный файл:

extern void aeError(const char *str, int code=1); 

extern void aeAssert(bool b, const char *failStr = "assertion failed"); 

Файл .cpp:

// Don't use inline and don't include the default argument values. 

void aeError(const char *str, int code) 
{ 
    throw std::runtime_error(str); 
    #ifdef AE_EXIT_AT_ERROR 
    std::exit(code); 
    #endif 
} 

void aeAssert(bool b, const char *failStr) 
{ 
    if(!b) 
     aeError(failStr); 
} 
+0

Означает ли это, что все стандартные функции C ('утверждает()', 'Fread()' и т.д. .), объявленные глобально, являются встроенными? – Pilpel

+0

@Pilpel, см. Обновленный ответ. Надеюсь, это уберет ваши сомнения. –

+0

Я сделал Error.cpp, который содержит функции, когда Error.h содержит только определения. Код все еще компилируется, когда я опускаю 'extern' из объявлений функций в Error.h. Действительно ли «extern» нужен? – Pilpel

Смежные вопросы