【问题标题】:C++ link error.. is invalid?C ++链接错误..无效?
【发布时间】:2015-02-22 19:30:06
【问题描述】:

我不断收到这个 Visual C++ 2010 LNK2005 链接器错误,说我对“Error.h”中包含的两个函数有多个定义。 (我为错误显示制作的标题)

我的项目是这样的:

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,我也尝试在 Error.h 中添加包含保护。

这是编译输出:

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

这可能是一个错误吗?

【问题讨论】:

    标签: c++ visual-studio-2010 linker


    【解决方案1】:

    当您在 .h 文件中定义函数时,将它们内联。否则,函数定义是#include它的所有.cpp文件的目标代码的一部分,具有外部链接。

    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 文件中。

    .h 文件:

    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);
    }
    

    【讨论】:

    • 这是否意味着所有全局声明的标准 c 函数(assert()fread() 等)都是内联的?
    • @Pilpel,请参阅更新后的答案。希望这能消除您的疑虑。
    • 我制作了一个包含函数的 Error.cpp,而 Error.h 仅包含定义。当我从 Error.h 中的函数声明中省略 extern 时,代码仍然可以编译。 extern 真的需要吗?
    • 不,函数不需要extern。变量需要它。两者都使用它会使声明看起来一致。
    猜你喜欢
    • 2013-08-09
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 2021-04-17
    • 2014-11-08
    相关资源
    最近更新 更多