错误C2011' vars :: strct':' struct'类型重新定义

时间:2018-06-16 22:24:15

标签: c++

vars.cpp

#pragma once
#include "vars.h"

namespace vars
{
    struct strct
    {
        bool enabled = false;
    };
}

vars.h

#pragma once

namespace vars
{
    extern struct strct
    {
        bool enabled = false;
    };
}

extern vars::strct *variables = new vars::strct[ 6 ];

我正在'vars::strct': 'struct' type redefinition in vars.cpp

问题是什么?

2 个答案:

答案 0 :(得分:1)

你已经两次定义了你的结构,这与one definition rule冲突,因而错误。如果您在vars.h中包含vars.cpp文件,则会在vars.cpp文件中定义该结构。

注意

您的extern文件中不需要vars.h关键字,因为您定义了一个结构而不是全局使用它的实例。有关详细信息,请参阅When to use extern in C++

此外,您在#pragma once文件中使用了.cpp。在大多数情况下,您不包含.cpp个文件,因此它是多余的。

答案 1 :(得分:0)

这里有一些问题。

extern是一个Storage Class Specifier,用作编译器的一个承诺,即使变量尚未找到它的定义,它也存在。可以安全地使用变量,链接器将负责跟踪以后定义的位置。

您无需将类型定义为extern,并且您可能正在接收诊断信息,告诉您。

所以修复1:从类型中删除extern

#pragma once

namespace vars
{
    struct strct
    {
        bool enabled = false;
    };
}

extern vars::strct *variables = new vars::strct[ 6 ];

现在编译vars.cpp时,将包含vars.h,将vars.cpp转换为

#pragma once
namespace vars
{
    extern struct strct
    {
        bool enabled = false;
    };
}

extern vars::strct *variables = new vars::strct[ 6 ];
namespace vars
{
    struct strct
    {
        bool enabled = false;
    };
}

很明显,strct定义了两次。 Vars.cpp不需要它自己的定义。删除它。

vars.cpp需要做的是兑现variables某处存在的承诺,将我们带到问题2。

extern vars::strct *variables = new vars::strct[ 6 ];

extern变量是变量存在的承诺。还没有variables,所以初始化它就是iffy。编译器似乎允许它,但编译器允许很多人类的愚蠢。

通常,您不希望标头中包含变量定义,因为包含标头的所有文件都会获得标头的副本。 #pragma once会合理地确定(我的知识仍有一些失败案例),每个Translation Unit只会包含一次标题。但每个翻译单元都有自己的定义,你就可以重新排序出多个定义错误了。

修复2:你真正想要的是

vars.h

#pragma once

namespace vars
{
    struct strct
    {
        bool enabled = false;
    };
}

extern vars::strct *variables; // variables exists somewhere

和vars.cpp

#include "vars.h"

vars::strct *variables = new vars::strct[ 6 ]; // variables exists here

现在只有一个变量和#include "vars.h"可以使用它的任何人,假设他们编译并链接vars.cpp。

请注意,#pragma once已从vars.cpp中删除。这是不必要的。如果你发现自己包含cpp文件,你就会在某处丢失。不要这样做。