cppannotations/annotations/yo/static/private.yo
Frank B. Brokken 777b182edd Moved all files but 'excluded', 'sf', and 'sourcetar' to ./annotations
This allowed me to standardize the sourcetar and sf/* scripts: the base
    directory (containing ./git) is now empty, except for maintenance scripts,
    while the source files and build scripts of the annotations are stored in
    a subdirectory of their own.
2013-05-29 20:44:08 +02:00

95 lines
4.1 KiB
Text

To illustrate the use of a static data member which is a private
variable in a class, consider the following:
verb(
class Directory
{
static char s_path[];
public:
// constructors, destructors, etc.
};
)
The data member tt(s_path[]) is a private static data member. During
the program's execution only em(one) tt(Directory::s_path[]) exists,
even though multiple objects of the class tt(Directory) may exist. This
data member could be inspected or altered by the constructor, destructor or by
any other member function of the class tt(Directory).
Since constructors are called for each new object of a class, static
data members hi(initialization: static data member)
hi(static data members: initialization) are not em(initialized) by
constructors. At most they are em(modified). The reason for this is that
static data members exist em(before) any constructor of the class has been
called. Static data members are initialized when they are defined, outside of
any member function, exactly like the initialization of ordinary (non-class)
global variables.
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 ti(data.cc).
The data member tt(s_path[]), used above, could thus be
defined and initialized as follows in a file tt(data.cc):
verb(
include "directory.ih"
char Directory::s_path[200] = "/usr/local";
)
In the class interface the static member is actually only em(declared). In
its implementation (definition) its type and class name are explicitly
mentioned. Note also that the i(size specification) can be left out of the
interface, as shown above. However, its size em(is) (either explicitly or
implicitly) required when it is defined.
Note that em(any) source file could contain the definition of the static
data members of a class. A separate tt(data.cc) source file is advised, but
the source file containing, e.g., tt(main()) could be used as well. Of course,
any source file defining static data of a class must also include the header
file of that class, in order for the static data member to be known to the
compiler.
A second example of a useful private static data member is given below. Assume
that a class tt(Graphics) defines the communication of a program with a
graphics-capable device (e.g., a VGA screen). The initialization 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 tt(static) flag variable
tt(s_nobjects). The variable tt(s_nobjects) simply counts the number of
tt(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
tt(Graphics) object ceases to exist. The class interface for this
tt(Graphics) class might be:
verb(
class Graphics
{
static int s_nobjects; // counts # of objects
public:
Graphics();
~Graphics(); // other members not shown.
private:
void setgraphicsmode(); // switch to graphics mode
void settextmode(); // switch to text-mode
}
)
The purpose of the variable tt(s_nobjects) is to count the number of
objects existing at a particular moment in time. When the first object is
created, the graphics device is initialized. At the destruction of the last
tt(Graphics) object, the switch from graphics mode to text mode is made:
verb(
int Graphics::s_nobjects = 0; // the static data member
Graphics::Graphics()
{
if (!s_nobjects++)
setgraphicsmode();
}
Graphics::~Graphics()
{
if (!--s_nobjects)
settextmode();
}
)
Obviously, when the class tt(Graphics) would define more than one
constructor, each constructor would need to increase the variable
tt(s_nobjects) and would possibly have to initialize the graphics mode.