C++ C++;命名空间未在Visual Studio 2019中编译

C++ C++;命名空间未在Visual Studio 2019中编译,c++,header-files,visual-studio-2019,C++,Header Files,Visual Studio 2019,我对为我正在进行的项目创建数学库很感兴趣,所以我创建了一个math.h文件,其中定义了名称空间“math”和“Vector3”类。我现在尝试在涉及Vector3的数学名称空间中定义一些数学助手函数: namespace Math { Vector3 Test() { return Vector3::Zero; } } 但是,当我尝试在main.cpp中包含“Math.h”并尝试调用它时 Vector3 test = Math::Test(); 我在Visual

我对为我正在进行的项目创建数学库很感兴趣,所以我创建了一个math.h文件,其中定义了名称空间“math”和“Vector3”类。我现在尝试在涉及Vector3的数学名称空间中定义一些数学助手函数:

namespace Math {
    Vector3 Test() {
        return Vector3::Zero;
    }
}
但是,当我尝试在main.cpp中包含“Math.h”并尝试调用它时

Vector3 test = Math::Test();
我在VisualStudio中遇到一个错误

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2005 "class Vector3 __cdecl Math::Test(void)" (?Test@Math@@YA?AVVector3@@XZ) already defined in Math.obj myproject"

我不确定是否需要使用我在命名空间中创建的类来执行某些操作?

如果我理解您试图执行的操作,则必须在源(.cpp)文件中定义函数,或者在头文件中将其定义为内联函数。否则,每次包含头时,基本上都在重复定义,这会让编译器不高兴

选项#1:在标题中内联:

#ifndef __MYHEADER_H__
#define __MYHEADER_H__

/* ... */

namespace Math {
    inline Vector3 Test() { return Vector3::Zero;}
}

/* ... */
#endif __MYHEADER_H__
注意:内联不会失败,因为编译器用定义的代码替换对Vector3::Test()的任何调用

选项#2:将定义放在源文件中,将声明放在头文件中。

#ifndef __MYHEADER_H__
#define __MYHEADER_H__

/* ... */

namespace Math {
    inline Vector3 Test() { return Vector3::Zero;}
}

/* ... */
#endif __MYHEADER_H__
头文件(例如:myheader.h):

源文件(例如myheader.cpp):


将源文件添加到您的项目/makefile/cmakelists.txt/which,您就可以开始了。

如果我理解您的意图,您必须在源(.cpp)文件中定义函数,或者在头文件中将其定义为内联函数。否则,每次包含头时,基本上都在重复定义,这会让编译器不高兴

选项#1:在标题中内联:

#ifndef __MYHEADER_H__
#define __MYHEADER_H__

/* ... */

namespace Math {
    inline Vector3 Test() { return Vector3::Zero;}
}

/* ... */
#endif __MYHEADER_H__
注意:内联不会失败,因为编译器用定义的代码替换对Vector3::Test()的任何调用

选项#2:将定义放在源文件中,将声明放在头文件中。

#ifndef __MYHEADER_H__
#define __MYHEADER_H__

/* ... */

namespace Math {
    inline Vector3 Test() { return Vector3::Zero;}
}

/* ... */
#endif __MYHEADER_H__
头文件(例如:myheader.h):

源文件(例如myheader.cpp):


将源文件添加到您的项目/makefile/cmakelists.txt/which,您就可以开始了。

当您使用
内联时,您也在重复定义。但是如果没有
inline
,可能只有一个定义(一个定义规则),但是如果使用
inline
,每个翻译单元中可能有定义,只要它们是相同的。@walnut是的。同一内联声明的不同定义将产生编译错误。不,同一内联
函数的多个不相同的定义通常不会导致编译错误。它使程序格式不正确,不需要诊断。另外,“注意:内联不会失败,因为编译器会用定义的代码替换对Vector3::Test()的任何调用”:这不适用于显示的代码<代码>内联并不意味着函数将内联。这只意味着使用该函数的每个翻译单元都将包含该函数的定义。此外,您应该避免使用
\uuuuu MYHEADER\u H\uuu
作为标题保护。包含双下划线或以下划线开头,后跟大写字母的标识符保留给编译器/标准库。声明它们或用这样的名称定义宏在理论上会导致未定义的行为,在实践中,如果您碰巧使用了实现实际使用的标识符,则会导致问题。请改用
MYHEADER\u H\u
或类似的方法。@walnut:非常好。当您使用
inline
时,您也在重复定义。但是如果没有
inline
,可能只有一个定义(一个定义规则),但是如果使用
inline
,每个翻译单元中可能有定义,只要它们是相同的。@walnut是的。同一内联声明的不同定义将产生编译错误。不,同一内联函数的多个不相同的定义通常不会导致编译错误。它使程序格式不正确,不需要诊断。另外,“注意:内联不会失败,因为编译器会用定义的代码替换对Vector3::Test()的任何调用”:这不适用于显示的代码<代码>内联并不意味着函数将内联。这只意味着使用该函数的每个翻译单元都将包含该函数的定义。此外,您应该避免使用
\uuuuu MYHEADER\u H\uuu
作为标题保护。包含双下划线或以下划线开头,后跟大写字母的标识符保留给编译器/标准库。声明它们或用这样的名称定义宏在理论上会导致未定义的行为,在实践中,如果您碰巧使用了实现实际使用的标识符,则会导致问题。请改用
MYHEADER\u H\u
或类似的方法。@walnut:非常好。错误消息不是编译错误。这是一个链接器错误。通常由在项目中的多个源文件中定义(实现)函数引起。由于您在头文件中定义了函数,因此将该头包含在多个源文件中(直接或间接)是原因。(1)内联标记函数,或(2)将定义移出头文件并移动到单个源文件中,并且只在头文件中声明函数。有关链接器工具错误LNK2005的更多详细信息,我建议您可以参考文档:请参阅示例:,。错误消息不是编译错误。这是一个链接器错误。通常由在项目中的多个源文件中定义(实现)函数引起。由于您在头文件中定义了函数,因此将该头包含在多个源文件中(直接或间接)是原因。要么(1)内联标记函数,要么(2)将定义从头文件移到单个源文件中,并且只有一个声明