There are a couple things going wrong here.
extern
is a Storage Class Specifier used as a promise to the compiler that a variable exists even if it has not yet found the definition of it. The variable can be safely used and the linker will take care of tracking where it has been defined later.
You do not need to define a type as extern
and you may be receiving a diagnostic telling you this.
So fix 1: Remove extern
from the type.
#pragma once
namespace vars
{
struct strct
{
bool enabled = false;
};
}
extern vars::strct *variables = new vars::strct[ 6 ];
Now when vars.cpp is compiled, vars.h will be includided, transforming vars.cpp into
#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;
};
}
And it's obvious that strct
is defined twice. Vars.cpp does not need it's own definition. Remove it.
What vars.cpp does need is to make good on the promise that somewhere variables
exists, bringing us to problem 2.
extern vars::strct *variables = new vars::strct[ 6 ];
An extern
variable is a promise that a variable exists. There is no variables
yet, so initializing it is iffy. The compiler seems to allow it, but the compiler allows a lot of human stupidity.
In general you do not want variable definitions in headers because all files that include a header get a copy of the header. #pragma once
will make reasonably sure (too my knowledge there are still a few failure cases) that the header only gets included once per Translation Unit. But each translation unit will have its own definition and you're right back into sorting out multiple definition errors.
Fix 2: What you really want is
vars.h
#pragma once
namespace vars
{
struct strct
{
bool enabled = false;
};
}
extern vars::strct *variables; // variables exists somewhere
and vars.cpp
#include "vars.h"
vars::strct *variables = new vars::strct[ 6 ]; // variables exists here
Now there is one and only one variables and anyone who #include "vars.h"
can use it, assuming they compile and link vars.cpp.
Note the #pragma once
has been removed from vars.cpp. It is unnecessary. If you find yourself including cpp files, you've gotten lost somewhere. Don't do it.