- Next chapter
- Previous chapter
- Table of contents

# Chapter 8: Static data and functions

> We're always interested in getting feedback. E-mail us if you like this guide, if you think that important material is omitted, if you encounter errors in the code examples or in the documentation, if you find any typos, or generally just if you feel like e-mailing. Mail to Frank Brokken or use an e-mail form. Please state the concerned document version, found in the title.

In the previous chapters we have shown examples of classes where each object of a class had its own set of `public` or `private` data. Each `public` or `private` function could access the object's own version of the data.

In some situations it may be desirable that one or more common data fields exist, which are accessible to all objects of the class. An example of such a situation is the name of the startup directory in a program which recursively scans the directory tree of a disk. A second example is a flag variable, which states whether some specific initialization has occurred: only the first object of the class would then perform the initialization and would then set the flag to `done'.

Such situations are analogous to C code, where several functions need to access the same variable. A common solution in C is to define all these functions in one source file and to declare the variable as a `static`: the variable name is then not known beyond the scope of the source file. This approach is quite valid, but doesn't stroke with our philosophy of one function per source file. Another C-solution is to give the variable in question an unusual name, e.g., `_6uldv8`, and then to hope that other program parts won't use this name by accident. Neither the first, nor the second C-like solution is elegant.

C++'s solution is to define `static` data and functions, common to all objects of a class, and inaccessible outside of the class. These functions and data will be discussed in this chapter.

## 8.1: Static data

A data member of a class can be declared `static`; be it in the `public` or `private` part of the class definition. Such a data member is created and initialized only once, in contrast to non-static data members, which are created again and again, for each separate object of the class. A `static` data member is created once: when the program starts executing. Nonetheless, it is still part of the class.

`static` data members which are declared `public` are like `normal' global variables: they can be reached by all code of the program using their name, together with their class name and the scope resolution operator. This is illustrated in the following code fragment:

        class Test
        {
            public:
                static int
                    public_int;
            private:
                static int
                    private_int;
        }

        int main()
        {
            Test::public_int = 145;     // ok

            Test::private_int = 12;     // wrong, don't touch
                                        // the private parts
            return (0);
        }

This code fragment is not suitable for consumption by a C++ compiler: it only illustrates the interface, and not the implementation of `static` data members. We will discuss the implementation of such members shortly.

### 8.1.1: Private static data

To illustrate the use of a `static` data member which is a `private` variable in a class, consider the following code fragment:

        class Directory
        {
            public:
                // constructors, destructors, etc. (not shown)
                ...
            private:
                // data members
                static char
                    path[];
        };

The data member `path[]` is a `private static` variable. During the execution of the program, only one `Directory::path[]` exists, even though more than one object of the class `Directory` may exist. This data member could be inspected or altered by the constructor, destructor or by any other member function of the class `Directory`.

Since constructors are called for each new object of a class, `static` data members are never initialized by constructors. At most they are modified. The reason for this is that the `static` data members exist before the constructor of the class is called for the very first time. The `static` data members can be initialized during their definition, outside of all member functions, in the same way as global variables are initialized. The definition and initialization of a `static` data member usually occurs in one of the source files of the class functions, preferably in a source file dedicated to the definition of static data members, called `data.cc`.

The data member `path[]` from the above class `Directory` could thus be defined and initialized in the source file of the constructor (or in a separate file `data.cc`):

        // the static data member: definition and initialization
        char
            Directory::path [200] = "/usr/local";

        // the default constructor
        Directory::Directory()
        {
            ...
        }

It should be noted that the definition of the `static` data member can occur in any source file; as long as it is defined only once. So, there is no need to define it in, e.g., a source file in which also a memberfunction of the class is implemented.

In the class interface the `static` member is actually only declared. At its implementation (definition) its type and class name are explicitly stated. Note also that the size specification can be left out of the interface, as is shown in the above array `path[]`. However, its size is needed at its implementation.

A second example of a useful `private static` data member is given below. A class `Graphics` defines the communication of a program with a graphics-capable device (e.g., a VGA screen). The initial preparing of the device, which in this case would be to switch from text mode to graphics mode, is an action of the constructor and depends on a `static` flag variable `nobjects`. The variable `nobjects` simply counts the number of `Graphics` objects which are present at one time. Similarly, the destructor of the class may switch back from graphics mode to text mode when the last `Graphics` object ceases to exist.

The class interface for this `Graphics` class might be:

        class Graphics
        {
            public:
                // constructor, destructor
                Graphics();
                ~Graphics();

                // other interface is not shown here,
                // e.g. to draw lines or whatever

            private:
                // counter of # of objects
                static int nobjects;

                // hypothetical functions to switch to graphics
                // mode or back to text mode
                void setgraphicsmode();
                void settextmode();
        }

The purpose of the variable `nobjects` is to count the number of objects which exist at one given time. When the first object is created, the graphics device is initialized. At the destruction of the last `Graphics` object, the switch from graphics mode to text mode is made:

        // the static data member
        int Graphics::nobjects = 0;

        // the constructor
        Graphics::Graphics()
        {
            if (! nobjects)
                setgraphicsmode();
            nobjects++;
        }

        // the destructor
        Graphics::~Graphics()
        {
            nobjects--;
            if (! nobjects)
                settextmode();
        }

It is obvious that when the class `Graphics` would define more than one constructor, each constructor would need to increase the variable `nobjects` and possibly would have to initialize the graphics mode.

### 8.1.2: Public static data

Data members can be declared in the `public` section of a class definition, although this is not common practice (such a setup would violate the principle of data hiding). E.g., when the `static` data member `path[]` from chapter 8.1 would be declared in the `public` section of the class definition, all program code could access this variable:

        int main()
        {
            getcwd(Directory::path, 199);
            return(0);
        }

Note that the variable `path` would still have to be defined. As before, the class interface would only declare the array `path[]`. This means that some source file would still need to contain the implementation:

        char
            Directory::path[200];

## 8.2: Static member functions

Besides `static` data, C++ allows the definition of `static` functions. Similar to the concept of `static` data, in which these variables are shared by all objects of the class, `static` functions apply to all objects of the class.

The `static` functions can therefore address only the `static` data of a class; non-`static` data are unavailable to these functions. If non-`static` data could be addressed, to which object would they belong? Similarly, `static` functions cannot call non-`static` functions of the class. All this is caused by the fact that `static` functions have no `this` pointer.

Functions which are `static` and which are declared in the `public` section of a class interface can be called without specifying an object of the class. This is illustrated in the following code fragment:

        class Directory
        {
            public:
                // constructors, destructors etc. not shown here
                ...
                // here's the static public function
                static void setpath(char const *newpath);

            private:
                // the static string
                static char path [];
        };

        // implementation of the static variable
        char Directory::path [199] = "/usr/local";

        // the static function
        void Directory::setpath(char const *newpath)
        {
            strncpy(path, newpath, 199);
        }

        // example of the usage
        int main()
        {
            // Alternative (1): calling setpath() without
            // an object of the class Directory
            Directory::setpath("/etc");

            // Alternative (2): with an object
            Directory
                dir;

            dir.setpath("/etc");

            return (0);
        }

In the example above the function `setpath()` is a `public static` function. C++ also allows `private static` functions: these functions can only be called from other member functions of the class of which they are themselves members, but not from other functions.

Note that such a `private static` function could only (a) access static variables, or (b) call other static functions: non-static code or data members would still be inaccessible to the static function.

- Next chapter
- Previous chapter
- Table of contents