结合使用内联数学库和预编译头文件时的链接错误

问题描述

|| 今天我遇到了一个很奇怪的问题。我有一个针对SSE优化的数学库,因此几乎所有功能都声明为内联。为了简化起见,我将仅使用Vector3类来解释该问题: Vector3在Vector3.h中声明,如下所示:
#ifndef VIRTUS_VECTOR3_H
#define VIRTUS_VECTOR3_H

#ifndef VEC3INLINE
  #if(_DEBUG)
    #define VEC3INLINE inline
  #else
    #define VEC3INLINE __forceinline
  #endif
#endif

namespace Virtus {

struct Vector3
{
  union
  {
    struct { f32 x,y,z; };
    f32 v[3];
  };

  Vector3(void);
  Vector3(const Vector3& rhs);
  Vector3(f32 xx,f32 yy,f32 zz);

  VEC3INLINE Vector3& operator=(const Vector3& rhs);

  VEC3INLINE Vector3 operator+(f32 rhs) const;
  VEC3INLINE Vector3 operator-(f32 rhs) const;
  VEC3INLINE Vector3 operator*(f32 rhs) const;
  VEC3INLINE Vector3 operator/(f32 rhs) const;
  VEC3INLINE Vector3& operator+=(f32 rhs);
  VEC3INLINE Vector3& operator-=(f32 rhs);
...

#include \"vector3.inl\"
#endif
在vector3.inl中,我继续定义所有功能
namespace Virtus {

Vector3::Vector3(void)
  : x(0.0f),y(0.0f),z(0.0f)
{
}

Vector3::Vector3(const Vector3& rhs)
  : x(rhs.x),y(rhs.y),z(rhs.z)
{
}

Vector3::Vector3(f32 xx,f32 zz)
  : x(xx),y(yy),z(zz)
{
    }

VEC3INLINE Vector3& Vector3::operator=(const Vector3& rhs)
{
  memcpy(v,rhs.v,sizeof(v));
  return *this;
}

    ...
然后,我将所有数学对象包含在名为math.h的文件
#ifndef VIRTUS_MATH_H
#define VIRTUS_MATH_H

#include \"vector2.h\"
#include \"vector3.h\"
#include \"vector4.h\"
#include \"matrix4.h\"
#include \"primesearch.h\"

namespace Virtus
{
  class MathException
  {
  public:
    enum ErrorCode
    {
      PRIME_SEARCH_INVALID_ELEMENTS,PRIME_SEARCH_UNSUFFNUM_PRIMES
    };

    MathException(ErrorCode code) : m_Error(code) {}
    ErrorCode What(void) const { return m_Error; }

  private:
    ErrorCode m_Error;
  };
} // namespace virtus

#endif // Include Guard
和math.h包含在我的预编译头文件中(precompiled.h aka stdafx.h) 我使用Visual Studio 2008,它应该自动生成过程中排除.inl文件。 这是我得到的链接错误:   错误1错误LNK2005:\“ public:   __thiscall Virtus :: Vector3 :: Vector3(void)\“   (?? 0Vector3 @ Virtus @@ QAE @ XZ)已经   定义于   precompiled.obj main.obj Virtus 我尝试了各种可能的解决方法,例如手动从构建中排除所有inl文件。在预编译的文件中不包括math.h,而是仅在需要时包含它(在这种情况下,我会收到类似的已经定义的链接错误);从inl扩展名更改为cpp扩展名,依此类推。我能够修复它的唯一方法是使用#pragma一次,而不是使用包括卫兵。因此,我目前最好的猜测是,它与预编译头文件和包含防护的组合有关,但我不确定如何解决此问题。 帮助将不胜感激!     

解决方法

        vector3.inl内部的每个定义都需要用
inline
明确定义。