regarding static/extern, some stuff diff between c and c++.
###################################
#### static local variable ####
###################################
static mem life cycle - once you declare it, it will exist until the program ends, as opposed to automatic mem life cycle where a variable is terminated once it reaches the end of the scope.
---------------------------------// main.cpp
#include <iostream>
#include "ken.cpp"
using namespace std;
int main()
{ // static | non-static
cout << getsta(9) << endl; // 109 | 109
cout << getsta(200) << endl; // 309 | 300
return 0;
}
--------------------------------
--------------------------------// ken.cpp
int getsta(int x){
static int val = 100; // "static"
val = val + x;
return val;
}
--------------------------------
static variables are guaranteed to get initialized to 0(zero) while non-static variables are not. (hense you should initialize them whereever possible.)
NOTE: in C++, mem allocation for static variables happens when the declaration part is reached, but in C, mem alloc for static var happens at the beginning of the program execution. this means, the below code will be ok with C++ while illegal in C.
-----------------------------------------------------------
void func(int x){
static int val = x; // illegal in C, legal in C++
}
-----------------------------------------------------------
##################################
### static global variable ### (to be distinguished from static "local" variable)
##################################
declaring a global variable with "static" keyword will restrict the variable to "file scope" (not program/global scope, not block scope.)
study the next section.
##################################################
### internal linkage VS external linkage ###
##################################################
internal/external linkage has to be understood along with the concept of program(global) scope, file scope, block scope.
global variables with static keyword will restrict the access from other files. (internal linkage)
non-static global variables can be accessed from other files via "extern" specifier. (external linkage)
# notice we are talking about "global" variables. i.e. variables that are outside any function definition.
using extern to refer to a static global variable from other file will not work. see the BAD example section below.
as shown below, to access static global var from other file, kinda like accessing encapsulated private var of a class, you need to implement some functions. generally speaking, a choice between using extern everywhere and using static global var with manipulator functions, the latter is preferred.
### static global var & extern example
----------------------------// test.h
void setval(int);
int getbar();
----------------------------// test.cpp
#include "test.h"
int foo = 100; // program scope
static int bar; // file scope
void setval(int x){
foo = foo + x;
bar = bar + x;
}
int getbar(){
return bar;
}
----------------------------// main.cpp
#include <iostream>
#include "test.h"
// don't include "test.cpp" here because linker will link the variables.
using namespace std;
int main()
{
extern int foo;
foo = foo * 2; // 200;
extern int bar; // this will not compile. undefined reference to 'bar'
setval(100); // foo is 300, bar is 100;
cout << foo << endl; // 300
cout << getbar() << endl; // 100
return 0;
}
-----------------------------
===> run $ g++ -o ext main.cpp test.cpp # this will link variables between files.
$ ext
#### BETTER example on extern usage
normally, the way we use extern is we put the extern declaration in a header file, and all the other files just refer to it, where one of the file actually defines it.
-------------------- // header.h
extern int foo;
void some_func();
...
-------------------- // src1.cpp
#include "header.h"
int foo; // this has to be a global var, i.e. external linkage. don't define this inside a func.
...
...
-------------------- // src2.cpp
#include "header.h"
void some_func(){
foo = 123;
}
--------------------
#### BAD example
in the below example, there will be two separate static global file-scope variables, one for each of foo.cpp and main.cpp
------------------------- // foo.h
static int foo;
void update_foo(int);
int getfoo();
------------------------- // foo.cpp
#include "foo.h"
extern int foo; // in fact, this line does not mean anything, you can remove it.
// once you included "foo.h" it declared static int foo in this file scope.
void update_foo(int x){
foo = foo + x;
}
int getfoo(){
return foo;
}
------------------------- // main.cpp
#include "foo.h"
#include <iostream>
using namespace std;
int main()
{
{
int local_foo = 100;
extern int foo;
foo = 123;
}
{
int local_foo;
local_foo += 100;
cout << local_foo << endl; // 100
extern int foo;
foo = foo + 123; // 246
}
cout << foo << endl; // 246
cout << getfoo() << endl; // 0
foo = foo + 1; // 247
update_foo(111);
cout << foo << endl; // 247
cout << getfoo() << endl; // 111
return 0;
}
------------------------
NOTE:
also, there is no guarantee on the initialization order when you have multiple static variables. (except in the same translation unit, which is essentially the same source file, initialization happens in the order of declaration). therefore, dont construct the initialization of static global variables definition depending on other static global variables.
(ref)
http://stackoverflow.com/questions/10422034/when-to-use-extern-in-c
http://stackoverflow.com/questions/14027317/what-is-the-difference-between-file-scope-and-program-scope
http://oshiete.goo.ne.jp/qa/3670390.html
http://www.learncpp.com/cpp-tutorial/43-file-scope-and-the-static-keyword/
http://forums.codeguru.com/showthread.php?157531-Difference-between-External-Linkage-and-internal-Linkage
http://okuyama.mt.tama.hosei.ac.jp/unix/C/slide82.html
############################
### static function ###
############################
this is a function version of a static global variable. "static" keyword will make the function internal linkage, only accessble within the same source file. this means you cannot declare a function prototype in a header file.
you use it when you want to define a func that shouldn't be accessed externally.
---------------------------- stafunc.h
void somefunc();
---------------------------- stafunc.cpp
#include "stafunc.h"
static void sta_func();
void somefunc(){
...
...
sta_func(); // legal
...
...
}
static void sta_func(){
...
...
...
}
---------------------------- main.cpp
#include "stafunc.h"
int main()
{ // cannot call sta_func() directly, only thru somefunc()
somefunc();
return 0;
}
----------------------------
simple enough.
#################################
### static member variable ### C++
#################################
a static global variable defined within a class.
---------------------------------- // stamem.h
class CFoo
{
public:
void set(int);
int get();
private:
static int bar;
};
---------------------------------- // stamem.cpp
#include "stamem.h"
int CFoo::bar = 123; // must define static member var outside the class def
// initialization is optional. if no explicit init val supplied, then it becomes zero.
// notice there is no "static" qualifier when defining.
// 'static' may not be used when defining (as opposed to declaring) a static data member
void CFoo::set(int x)
{
CFoo::bar = x;
// bar = x; // these will work alternatively
// this->bar = x;
}
int CFoo::get()
{
return CFoo::bar;
}
---------------------------------- // main.cpp
#include "stamem.h"
#include <iostream>
using namespace std;
int main()
{
CFoo cf1, cf2;
cout << cf1.get() << endl; // 123
cf1.set(456);
cf2.set(321);
cout << cf1.get() << endl; // 321
cout << cf2.get() << endl; // 321
return 0;
}
----------------------------------
=======> in the above example, if you make bar "public" static member variable, then you can access it without instantiating any class object of CFoo.
e.g. // this is not always a good use.
---------------------------------- // stamem.h
class CFoo
{
public:
static int bar; // you cannot initialize here
static const int baz = 123; // if static 'const' then initialization allowed
};
---------------------------------- // main.cpp
#include "stamem.h"
#include <iostream>
using namespace std;
int CFoo::bar = 777; // this is a definition, which you can do, and will have to need to do, regardless of private|public.
int main()
{
CFoo::bar = 666; // this you can do if it's public.
// notice how you never instantiated the class but still can access the var.
cout << CFoo:bar << endl; // 666
CFoo cf;
cout << cf.bar << endl; // 666
return 0;
}
----------------------------------
##################################
### static member function ### C++
##################################
- just like static member variable, static member function exist before the class gets instantiated.
- because of this nature, static member function cannot access non-static member variables which can only exist after an actual class instantiation.
- similarly, static member function cannot call non-static member function. technically non-static member function exist without class instantiation but since non-static member functions most likely access non-static member variables, we just ban static member function call non-static member function.
- also, no "this" pointer cos static member func does not exist per instance.
------------------------------------------------ // smf.h
class CFoo
{
public:
static int multiply(int& x){ return x *= 2;}
};
------------------------------------------------ // main.cpp
#include <iostream>
#include "smf.h"
using namespace std;
int main()
{
int num = 7;
cout << CFoo::multiply(num) << endl; // 14
CFoo cf;
cout << cf.multiply(num) << endl; // 28
return 0;
}
------------------------------------------------
==========> notice in the above example, if it's just only static member function, you are better off using namespace instead.
------------------------------------------------ // main.cpp
#include <iostream>
using namespace std;
namespace CFoo
{
int multiply(int& x){ return x *= 2;} // no need to make it static
}
int main()
{
int num = 7;
cout << CFoo::multiply(num) << endl; // 14
return 0;
}
------------------------------------------------
==========> notice how it's exactly the same but simpler.
- if defining a static member function outside the class def, then do NOT put 'static' keyword. (this rule is the same for static mem var)
e.g.
---------------------------------------------
class CFoo
{
public:
static int multiply(int&);
}
int CFoo::multiple(int& x)
{
return x *= 2;
}
--------------------------------------------