Sometimes it is useful and important to have variables that belong to the class and are shared by all objects. For example, what if we wanted to have a count of how many objects had been instantiated. (I feel bold and strong when I use big words like "instantiated" -- and they are the official words, so get with it, "man up" -- I can hear you whining about all this new language).
It is easy. Put the word "static" in front of the variable and you are done.
class Zombie { ... private: static int count = 0; };Note that we can provide an initial value.
We can also have static methods! When we use "normal" methods (i.e. "instance methods") we have to prefix them with an object as in z.greet(). To call a static method, we prefix it by the class name using this syntax:
x = Klass::get_count();When will you need such things. You will know.
#include <cstdio> #include <string> using namespace std; class Clam { public: Clam ( int xyz = 999 ) { _value = xyz; } void show ( void ); void set ( int ); Clam operator+ ( const Clam& ); private: int _value; }; inline void Clam::show ( void ) { printf ( "%d\n", _value ); } inline void Clam::set ( int xyz ) { _value = xyz; } inline Clam Clam::operator+ ( const Clam &arg ) { return Clam ( _value + arg._value ); } int main () { Clam c ( 42 ); c.show (); Clam d = c; d.set ( 13 ); d.show (); Clam x = c + d; x.show (); }Once again, this is a complete program, fully tested, that you can copy and run yourself.
The key thing to observe here is the "operator+" business which introduces the overloading of the infix "+" operator for addition. The "Clam" class here is just for demonstration and is nothing more than a container for a single integer. I was somewhat surprised that I get assignment of two class objects for free! This is not always the case. If your class contains some kind of storage allocated using "new" you will need to provide your own special "Clam" constructor that handles construction given an object as an argument.
We add the two objects "c" and "d" to get "x" and the show gives us the value 55. Voila!
#include <cstdio> #include <string> using namespace std; class Clam; class Grab { public: Grab ( int xyz = 999 ) { _info = xyz; } void show ( void ); void gimmee ( const Clam& ); private: int _info; }; class Clam { public: Clam ( int xyz = 999 ) { _value = xyz; } void show ( void ); friend void Grab::gimmee ( const Clam& ); private: int _value; }; inline void Clam::show ( void ) { printf ( "%d\n", _value ); } inline void Grab::show ( void ) { printf ( "%d\n", _info ); } inline void Grab::gimmee ( const Clam & xx ) { _info = xx._value; } int main () { Clam c ( 42 ); c.show (); Grab g ( 123 ); g.gimmee ( c ); g.show (); }I try to keep it simple. Honestly I do. There is really only one line here that is exciting, with the word "friend". Here is the idea. The "Grab" class is pretty much exactly the same as the "Clam" class -- just a container for a single integer for purposes of illustration. But I want to add a "gimmee" method to the "Grab" class that will extract the integer value from an object of the "Clam" class. Since "_value" is private, that would ordinarily be illegal. But by declaring Grab::gimmee a friend, we give it access to private stuff.
A couple of things are worth noting. One is the idiom of passing objects by reference and declaring them "const". This lets the compiler know it can avoid copying the whole object and seems to be a common and good practice (not necessary mind you, but good).
The other thing to note is the line:
class Clam;We have a sort of chicken and egg problem with the two classes needing to refer to each other. Each one needs to come before the other. This solves the problem and makes the compiler happy.
Tom's Computer Info / tom@mmto.org