已经在 .obj 中定义,即使有 #ifndef #define #endif

already defined in .obj even though with #ifndef #define #endif

本文关键字:#ifndef #define #endif obj 定义      更新时间:2023-10-16

所以我在头文件中有一个嵌套的命名空间。在命名空间中,我有一些独立的数据。但是在编译时,我得到了一个"已经在<中定义"。>.obj"。我尝试弄乱内联,但显然内联仅适用于函数。 这是我的代码:

#ifndef HEADER_H
#define HEADER_H
namespace sod {
namespace e {
const int _2D = 0;
const int _3D = 1;
const int _CUSTOM = 2;
const char *text1 = "I AM A C STRING";       // <-- char const * const sod::e::text1 (?text1@e@sod@@3PBDB) already defined in main.obj
const char *text2 = "I AM ALSO A C STRING";  // <-- char const * const sod::e::text2 (?text2@e@sod@@3PBDB) already defined in main.obj
};
};
#endif

我使用的编辑器是Visual Studio 2017。

任何帮助,不胜感激。

您的整数常量具有内部链接,因为它们被声明为const。具体正因为如此,即使此头文件包含在多个翻译单元中,它们也不会产生多个定义错误。

您的字符串指针具有外部链接,因为它们声明为const。因此,当此头文件包含在多个翻译单元中时,您最终会出现多个定义错误。不允许在程序中对具有外部链接的对象进行多个非内联定义。

如果你希望你的字符串指针是const的,就像你的整数一样,你应该这样声明它们

const char *const text = "whatever";

请注意声明中额外const的位置。

但是,如果您希望指针成为可修改的全局变量,那么情况就不同了。在 C++17 编译器中,您只需添加inline即可实现这一点

inline const char *text = "whatever";

在 C++17 之前,您必须跳过更复杂的箍组合和头文件中的extern声明。(在此处搜索有关全局变量的主题 - SO 对此有很好的介绍。

附言包含保护与避免链接器错误无关。

有人发布了对我有帮助的正确答案,但我认为他们删除了该帖子。

简单的答案是使用extern.

在我的头文件中:

#ifndef HEADER_H
#define HEADER_H
namespace sod {
namespace e {
extern const int _2D;
extern const int _3D;
extern const int _CUSTOM;
extern const char *text1;
extern const char *text2;
};
};

在 cpp 文件中:

#include "header.h"
namespace sod {
namespace e {
const int _2D = 0;
const int _3D = 1;
const int _CUSTOM = 2;
const char *text1 = "I AM A C STRING";
const char *text2 = "I AM ALSO A C STRING";
};
};