I think I hvae a fundamental misunderstanding of namespace and/or static variable. But I have tried this test code (typed by hand, forgive typos)
test.h:
namespace test{
static int testNum=5;
void setNum(int value);
}
main.cpp:
#include <test.h>
int test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
when I run this I get the value 5, not 9 as I would have expected. It seems almost as if I have two instances of the testNum variable, but that seems to be the exact opposite of what static should be doing. I'm guessing I've made a mistake in assuming that these features were identical to their java equvilants somehow...
I also get an error stating that testNum is declared multuple times if I remove the static from my declaration of testNum, could someone explain why that is the case as well?
Thank you
You might want to make sure your code actually has problems before you post it asking what's wrong ;)
I copy/pasted and fixed your typos, and manually did the include:
result:
What you haven't said is what else is in your program. If you have more than just main.cpp, and include your test.h, then each .cpp file will have its own copy of testNum. If you want them to share then you need all but one to mark it as
extern
.First, your misunderstanding has nothing to do with namespaces, it's only about
static
. For the rest of this answer I'm going to refer to simplytestNum
because the fact it's in a namespace is irrelevant.I'm also assuming you have another file, probably called
test.cpp
, which also includestest.h
and defines thesetNum
function.When a variable or function at namespace-scope (i.e. not a class member or local to a function) is declared
static
it means the entity's name is internal to that file. Formally it has "internal linkage", meaning it can't be referred to by name or linked to from other files (it can be indirectly referred to through a pointer or by passing it as an argument to another function.) That means if several files definestatic int testNum
then each file has its own internal variable with that name, distinct from thetestNum
in every other file (in fact one file could havestatic int testnum
and another could havestatic double testnum
and anotherstatic char* testNum
, they'd all be distinct and internal to each file.) If you put a definition like that in header then every file that includes the header has its owntestNum
.So with
static
on your variable in a header you have a different variable calledtestNum
in every file that includestest.h
. That means if you settestNum
in one file and call a function in a different file which usestestNum
it refers to a different variable, which just happens to have the same name.Because of this, declaring non-const
static
variables in headers is almost always wrong.Without
static
you would have a definition of thetestNum
variable in every file that includestest.h
, which is not allowed: every entity must be defined once and once only in your program. The way to solve that is to declare the variable in the header, but not define it, which you do by telling the compiler the variable isextern
:That tells the compiler there is a variable with "external linkage" called
testNum
, so when code refers totestNum
it will always mean the same variable (not some name with internal linakge that is a different entity in every file.) After declaring anextern
variable it is your responsibility to ensure there is exactly one definition provided somewhere in the program, so in exactly one file (i.e. not in a header that gets included in multiple files) you define it:static
at namespace scope is a misnomer, and shouldn't be used. It means simply that the entity declared static has internal name binding; in other words, that the same name in other translation units will refer to a different entity, and in the case of variable definitions, that there will be a separate instance of the variable in each translation unit. It has no effect on lifetime. (All variables declared or defined at namespace scope have static lifetime.)static
at namespace scope is also deprecated. Don't use it.With regards to declaring a variable in a header: prefix it with
extern
, and notstatic
. If a variable is declaredextern
, and there is no initialization, the declaration is not a definition. Of course, in this case, you must provide a definition somewhere (in a single source file). Something along the lines of:EDIT:
To clarify somewhat: there is some confusion here between lifetime and name binding:
Do not confuse the keyword
static
with static lifetime. (Functions can bestatic
, but functions have no defined lifetime in C++; they're just there.)The rules regarding these are not very orthognal. Basically, with regards to lifetime:
static
, andstatic
. regards to lifetime.Objects with static lifetime come into being sometime before
main
, and live until after you return frommain
.With regards to name binding:
static
, in which case they have internal name binding (but this use ofstatic
is deprecated), or if they areconst
, and are not declaredextern
,static
, andFinally, there is the question of whether a declaration is a definition or not. If it is a definition, memory is allocated and the object is (or may be) initialized. If it is not a definition, it simply tells the compiler that there is a definition somewhere else for the entity (object) declared in the declaration. In general, a variable declaration is a definition unless it is declared
extern
and does not have an initializer.