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

时间:2018-06-09 19:01:26

标签: c++ namespaces linker-errors

所以我在头文件中有一个嵌套的命名空间。在命名空间内我有一些独立的数据。但是在编译时,我得到了一个"已经在< ..> .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。

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

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

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

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

const char *const text = "whatever";

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

但如果你的指针是可修改的全局变量,那么它就是另一回事了。在C ++ 17编译器中,只需添加inline

即可实现
inline const char *text = "whatever";

在C ++之前的版本17中,你必须在头文件中跳过更复杂的箍与extern声明的组合。 (在这里搜索关于全局变量的主题 - 它在SO上有很好的涵盖。)

P.S。包含保护与避免链接器错误无关。

答案 1 :(得分:1)

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

简单的答案是使用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";
    };
};