2012-04-18 121 views
0

我正在使用Code :: Blocks。當我創建了一個頭文件foo.h並提出申述以及實施進去,編譯工作正常。創建一個foo.cpp文件並且不做任何事情仍然有效。但是,當我將頭文件包含在實現文件中,但是將頭文件保存在頭文件中時,我得到一個關於multiple declarations的錯誤。關於頭文件和執行文件之間的關係感到困惑

實例從我目前的項目

// header-file `GKit/math/blendprocs.cpp` 
#include "GKit/utils/Color.h" 

#ifndef _GKIT_MATH_BLENDPROCS_H_ 
#define _GKIT_MATH_BLENDPROCS_H_ 

    namespace GKit { 
     namespace math { 

      void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) { 
       D.a = A.a + (1 - A.a) * B.a; 
       D.r = (A.a * A.r + (1 - A.a) * B.a * B.r)/D.a; 
       D.g = (A.a * A.g + (1 - A.a) * B.a * B.g)/D.a; 
       D.b = (A.a * A.b + (1 - A.a) * B.a * B.b)/D.a; 
       GKIT_UTILS_COLOR_NORMALIZE(D); 
      } 

     } 
    } 

#endif // _GKIT_MATH_BLENDPROCS_H_ 

// implementation-file `GKit/math/blendprocs.cpp` 
#include "GKit/math/blendprocs.h" 

// Compilation output 
-------------- Build: Debug in GKit --------------- 

Compiling: GKit\math\blendprocs.cpp 
Linking console executable: bin_debug\GKit.exe 
build_debug\GKit\math\blendprocs.o:C:\Users\niklas\Desktop\GKit/./GKit/math/blendprocs.h:10: multiple definition of `GKit::math::blendAoverB(GKit::utils::Color const&, GKit::utils::Color const&, GKit::utils::Color&)' 
build_debug\main.o:C:\Users\niklas\Desktop\GKit/./GKit/math/blendprocs.h:10: first defined here 
collect2: ld returned 1 exit status 
Process terminated with status 1 (0 minutes, 0 seconds) 
2 errors, 0 warnings 

能否請你幫我理解這個錯誤?

回答

1

您在頭有一個定義。這個定義將在包括頭任何源文件被複制;因爲它通常是具有在程序多於一個定義一個錯誤,生成失敗這被稱爲在一個定義規則,有時含糊稱爲ODR

兩個最好的選擇是要麼:

  • 移動定義成源文件,只留下一個聲明在報頭中,或者
  • 添加inline的定義;這放鬆了規則並允許程序中的多個定義,只要它們全都相同即可。

而且,你不應該對你有警衛使用保留名稱;您應該從_GKIT_MATH_BLENDPROCS_H_中刪除最初的_;並且最好把這些看守放在標題的開頭,在任何#include指令之前。

1

在你的頭文件,你通常只放:

// header-file `GKit/math/blendprocs.cpp` 
#ifndef _GKIT_MATH_BLENDPROCS_H_ 
#define _GKIT_MATH_BLENDPROCS_H_ 

#include "GKit/utils/Color.h" 

namespace GKit { 
    namespace math { 

     void blendAoverB(GKIT_COLORBLENDPROC_ARGSX); 

    } 
} 

#endif // _GKIT_MATH_BLENDPROCS_H_ 

,然後在CPP文件你把實際執行:

// implementation-file `GKit/math/blendprocs.cpp` 
#include "GKit/math/blendprocs.h" 

namespace GKit { 
    namespace math { 

     void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) { 
      D.a = A.a + (1 - A.a) * B.a; 
      D.r = (A.a * A.r + (1 - A.a) * B.a * B.r)/D.a; 
      D.g = (A.a * A.g + (1 - A.a) * B.a * B.g)/D.a; 
      D.b = (A.a * A.b + (1 - A.a) * B.a * B.b)/D.a; 
      GKIT_UTILS_COLOR_NORMALIZE(D); 
     } 

    } 
} 

否則你的函數的執行將結束所有CPP文件都包含頭文件,當它試圖解析地址blendAoverB時會混淆鏈接器,因爲它可以在所有對象文件中找到它,相應的CPP文件包含帶有實現的頭文件。

在一個側面說明,這是更好地把包括得分後衛(在頭文件別的前#ifndef _GKIT_MATH_BLENDPROCS_H_(可能除了徵求意見)。

1

您應該內嵌您的實施或將實施cpp文件,不能同時使用。

// header "GKit/math/blendprocs.h" 
#pragma once 

#include "GKit/utils/Color.h" 

namespace GKit { 
     namespace math { 
      void blendAoverB(GKIT_COLORBLENDPROC_ARGSX); 
     } 
    } 

// implementation "GKit/math/blendprocs.cpp" 
#include "GKit/math/blendprocs.h" 

namespace GKit { 
     namespace math { 

      void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) { 
       D.a = A.a + (1 - A.a) * B.a; 
       D.r = (A.a * A.r + (1 - A.a) * B.a * B.r)/D.a; 
       D.g = (A.a * A.g + (1 - A.a) * B.a * B.g)/D.a; 
       D.b = (A.a * A.b + (1 - A.a) * B.a * B.b)/D.a; 
       GKIT_UTILS_COLOR_NORMALIZE(D); 
      } 

     } 
    } 

或者使用inline關鍵字交替地在標題中內嵌它。

// header "GKit/math/blendprocs.h" 
#pragma once 

#include "GKit/utils/Color.h" 

    namespace GKit { 
     namespace math { 
      inline void blendAoverB(GKIT_COLORBLENDPROC_ARGSX) { 
       D.a = A.a + (1 - A.a) * B.a; 
       D.r = (A.a * A.r + (1 - A.a) * B.a * B.r)/D.a; 
       D.g = (A.a * A.g + (1 - A.a) * B.a * B.g)/D.a; 
       D.b = (A.a * A.b + (1 - A.a) * B.a * B.b)/D.a; 
       GKIT_UTILS_COLOR_NORMALIZE(D); 
      } 
     } 
    }