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
问题是什么?
答案 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文件,你就会在某处丢失。不要这样做。