【问题标题】:Linker errors even though I prevent them with #ifndef链接器错误,即使我用#ifndef 阻止它们
【发布时间】:2011-01-08 16:09:34
【问题描述】:

我收到的链接器错误提示我没有使用 #ifndef 和 #define。

1>TGALoader.obj:错误 LNK2005: “结构 TGA tga” (?tga@@3UTGA@@A) 已在 main.obj 中定义 1>TGALoader.obj:错误 LNK2005: “结构 TGAHeader tgaheader” (?tgaheader@@3UTGAHeader@@A) 已经 在 main.obj 1>TGALoader.obj 中定义: 错误 LNK2005:“无符号字符 * uTGAcompare" (?uTGAcompare@@3PAEA) 已在 main.obj 中定义 1>TGALoader.obj:错误 LNK2005: “无符号字符 * cTGAcompare” (?cTGAcompare@@3PAEA) 已定义 在 main.obj 1>LINK 中:警告 LNK4098: defaultlib 'LIBCMTD' 与 使用其他库;采用 /NODEFAULTLIB:库

我已将 nehe opengl 教程中的头文件 Texture.h 和 tga.h 包含到我的 项目。我有

#ifndef TGAISCOOL
#define TGAISCOOL
#endif

在我的 tga.h 文件中。如果我不止一次包含这个,我会从上面粘贴的链接器中得到错误。前两个来自 texture.h,虽然情况是一样的。

有什么想法吗?

【问题讨论】:

  • 链接器错误与#ifndef 无关。标头保护仅在编译时防止重新定义冲突,即每个翻译单元。这个问题完全不同!

标签: c++ visual-studio-2008 linker linker-errors


【解决方案1】:

你没有做错任何事。问题在于您从 NeHe 获得的 Tga.h 文件。这个头文件定义了四个对象,这意味着如果你将文件包含在不同的翻译单元中,这些符号将出现多次,这就是链接器所抱怨的。

解决方法是将这些对象的定义移动到 Tga.cpp 文件中。

Tga.h 中以前有定义的行现在应该改为

extern TGAHeader tgaheader;
extern TGA tga;

extern GLubyte uTGAcompare[12];
extern GLubyte cTGAcompare[12];

这些行的原始版本现在在 Tga.cpp 中

【讨论】:

    【解决方案2】:

    问题是您将定义而不是声明放在头文件中。

    包含保护仅适用于单个翻译单元(即源文件)的多个包含。如果你编译多个翻译单元,每个翻译单元都会看到你的头文件的内容。

    所以,不要把这个定义放在你的头文件中:

    struct TGA tga;
    

    你想把这个声明放在你的头文件中:

    /* whatever.h */
    extern struct TGA tga;
    

    然后在源文件中添加定义:

    /* whatever.c */
    #include "whatever.h"
    
    struct TGA ta;
    

    经验法则是定义放在源文件中,声明放在头文件中。

    【讨论】:

    • 静态/内联定义在头文件中很好;它在出现问题的多个翻译单元中有外部可见的。
    • @ephemient - 我绝对承认内联定义的观点。但是虽然静态定义在技术上在头文件中可以正常工作,但我认为它们是如此可怕的风格,不值得一提。
    • 我的意思是“经验法则”,即“具有广泛应用的原则,并非严格准确。”
    • 我已经尝试过了,但一无所获。 :( 只是更多的编译器错误让我很难过。奇怪的是我以前从未遇到过他的问题。如果 Ifndef 没有像我预期的那样工作,我应该如何在 .h 文件中定义一个结构?
    • @bobber205 - 使用新版本的代码和遇到的编译错误更新问题。
    【解决方案3】:

    没有理由断定#ifndef 工作不正常。错误消息的意思是您在多个翻译单元(.obj 文件)中定义了具有相同名称的项目。因此,链接过程失败。

    至于如何修复,我们需要看更多代码。

    【讨论】:

    • 我很好奇如何处理这个请求。我有很多行代码要粘贴。我究竟需要包括什么?有什么地方可以压缩我的整个解决方案吗?
    • @bobber205:gist.github.com 是一种简单的分享方式,但您也应该尽量减少可重现的最小测试用例。换句话说,在仍然证明失败的同时摆脱任何可以做的事情。
    【解决方案4】:

    像这样改变你的 Tga.H:

    #ifndef Tga_H
    #define Tga_H
    #include "Texture.h"
    
    
    
    struct TGAHeader
    {
        GLubyte Header[12];                                 // TGA File Header
    } ;
    
    
    struct TGA
    {
        GLubyte     header[6];                              // First 6 Useful Bytes From The Header
        GLuint      bytesPerPixel;                          // Holds Number Of Bytes Per Pixel Used In The TGA File
        GLuint      imageSize;                              // Used To Store The Image Size When Setting Aside Ram
        GLuint      temp;                                   // Temporary Variable
        GLuint      type;   
        GLuint      Height;                                 //Height of Image
        GLuint      Width;                                  //Width ofImage
        GLuint      Bpp;                                    // Bits Per Pixel
    } ;
    
    
    extern  TGAHeader tgaheader;                                    // TGA header
    extern  TGA tga;                                                // TGA image data
    
    
    
    extern GLubyte uTGAcompare[12]; // Uncompressed TGA Header
    extern GLubyte cTGAcompare[12]; // Compressed TGA Header
    bool LoadTGA(Texture * , char * );
    bool LoadUncompressedTGA(Texture *, char *, FILE *);    // Load an Uncompressed file
    bool LoadCompressedTGA(Texture *, char *, FILE *);      // Load a Compressed file
    
    #endif
    

    在顶部的 TGALoader.cpp 文件中添加以下行:

    TGAHeader tgaheader;
    TGA tga;
    GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0};
    GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
    

    【讨论】:

      猜你喜欢
      • 2015-09-22
      • 1970-01-01
      • 2015-12-11
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多