void doStuff(void) {If you add "static" to a local variable, this makes the local variable retain its value permanently--the value is not destroyed when your function returns. So this prints "count = 1", then "count = 2", then "count = 3":
int count=0; /* not static: get a new count every call */
count++;
cout<<"count = "<<count<<"\n";
}
int foo(void) {
for (int i=0;i<3;i++) doStuff();
return 0;
}
void doStuff(void) {
static int count=0; /* static local: retain value across calls */
count++;
cout<<"count = "<<count<<"\n";
}
int foo(void) {
for (int i=0;i<3;i++) doStuff();
return 0;
}
static int my_x=17; /* acts like a global, but can't be seen from outside this file */
int foo(void) {
return my_x;
}
This is handy in bigger programs, where there might be several
different functions named "print()", which would normally cause a
conflict; but as long as they're declared static ("with static
linkage") they stay separate.
class Bar {If you add "static" before a class member, then the member acts like a global variable: it's shared between all instances of the class, and you don't need to create a class instance to access the variable. To refer to the variable, you say "classname::variablename":
public:
int value; // ordinary instance variable
};
int foo(void) {
Bar b;
b.value=17;
return b.value;
}
class Bar {You also have to actually declare the storage for a static member variable, because it's not automatically allocated like with ordinary members.
public:
static int value; // "static" makes this like a global, not per-instance
};
int foo(void) {
return Bar::value;
}
int Bar::value = 17; // must declare storage and initialize the value
class Bar {Static member functions are sometimes used to create class instances (a "factory" method), or to perform book-keeping for the class.
public:
static int doStuff(void) {cout<<"the doStuff method\n"; return 0;}
};
int foo(void) {
return Bar::doStuff();
}
"static" on a... |
does... |
which is useful for... |
local variable |
keep value across function calls |
counters and caches inside a function. |
global variable |
hides the variable from outside files |
avoiding conflicts in big programs |
function |
hides the fun ction from outside files | avoiding link conflicts in big programs |
member variable |
shares variable across instances |
class-local constants, counters and caches |
member function |
shares function across instances |
class-related housekeeping |
class Clam {But you can make this work by making the Clam a "friend" of the Diver. The "friend" line can go anywhere inside the Clam declaration:
private:
int pearl;
public:
Clam() {pearl=7;}
};
class Diver {
public:
int search(Clam &c) {
return c.pearl; // oops! Access error!
}
};
int foo(void) {
Clam c;
Diver d;
return d.search(c);
}
class Clam {Note that this is a really weird version of friendship: your friend can access all your private variables, like he has a key to your house. "friend" is not commutative: just because he's got a key to your house, you don't have a key to his house. Having too many "friend"s is hence pretty dangerous, because any of them can ransack your house, and you won't even know which one did it.
private:
int pearl;
public:
Clam() {pearl=7;}
friend class Diver; // the Diver can access my private pearl
};
class Clam {You can even define the entire "friend" function inside your class. This gives a little nicer syntax than a static method (which would be "Clam::shazam"):
private:
int pearl;
public:
Clam() {pearl=7;}
friend int foo(void); // the foo function can access my private pearl
};
int foo(void) {
Clam c;
return c.pearl;
}
class Clam {The "shazam" function doesn't even exist outside my class here. One strange caveat: "friend" functions can only be defined inside a class if they mention the name of the class in their argument list ("argument dependent lookup"), or if they have a predefined function prototype. If neither of these is true (for example, a "friend int ted(int x) { ... }"), then a friend function defined inside a class is totally inaccessible!
private:
int pearl;
public:
Clam() {pearl=7;}
friend int shazam(Clam &c) { // a *separate* function as a friend
return c.pearl;
}
};
int foo(void) {
Clam c;
return shazam(c);
}