Constants In A Uml Diagram
9.12. static Data And Functions
Object-oriented programs allocate memory for member variables inside objects, binding the variables to those objects. So, in a sense, the variables "belong" to the object (and Java calls them instance variables). Programmers access member variables through the bound object with one of the selection operators, either dot or arrow. However, there are situations where programmers may wish to store information associated with an entire class rather than individual objects, or create symbolic constants with class scope. C++ and Java implement class variables with the static
keyword. Both languages preserve encapsulation by accessing class variables with static
functions (or methods).
static And UML Diagrams
Non-static class features (attributes or operations) belong to individual instances of the class (i.e., to an object). In a C++ program, these features are bound to the object with the "this" pointer. On the other hand, static features belong to the class. Unless otherwise specified, features in a UML class diagram are non-static. The UML denotes static features by underlining the feature in the class diagram. Programmers translate the underlining to the static
keyword when they translate the UML class diagram to C++.
![The UML widget class diagram. widget ------------------- -count : int [underlined in the UML diagram] -color : int -alignment : float ------------------- +widget() +draw() : void +get_count() : int [underlined in the UML diagram] +get_color() : int +set_color(a_color : int) : void](https://icarus.cs.weber.edu/~dab/cs1410/textbook/9.Classes_And_Objects/images/uml_static.png)
static
keyword may modify attributes and operations alike, and is independent of other modifiers such as public
or private
. The Scope Resolution Operator
Programs can access static
variables, functions, and even constants through objects. However, these features "belong" to a class, so they exist even when the program hasn't instantiated any objects from the class. Therefore, we must have some notation to access static
features without relying on objects. That notation, preferred over using objects even if the program has them, is based on the scope resolution operator, ::
.
The scope resolution operator has two operands. The left-hand operand is the name of a scoping construct (e.g., a class or namespace). The right-hand operand is the name of a class feature (a member variable or function). The operator binds the feature to the named class's scope. The operator's name suggests that the scope resolution operator helps the compiler resolve an identifier's or a name's scope. If a program includes two or more functions with the same name and parameter list, programmers use the scope resolution operator to clarify which function they are calling. We'll use the operator extensively for this purpose when we introduce multi-class programs in the next chapter.
static Variables
We use static
variables whenever we need to save data that is related to a class but not bound to a particular object. A simple example is counting how many times a program instantiates a class (i.e., how many objects it creates). We encounter several problems if we make the counter a member variable:
- If we define the counter as a member variable, we will at best duplicate the data throughout all the instantiated objects. Furthermore, maintaining the correct count in all the objects will introduce a significant amount of additional logic.
- The counter is an accumulator. So, where should we initialize it? If we initialize it in the constructor or some other function, we'll reset the count whenever the program creates a new object. Again, preventing this will entail a significant amount of additional logic.
- The count is lost when the program destroys all the counted objects.
static
variables solve these problems. Foo.h | Foo.cpp |
---|---|
class Foo { private: static int count; public: Foo(); static int get_count(); }; | #include "foo.h" int Foo::count = 0; foo::foo() { count++; } int foo::get_count() { return count; } |
(a) | (b) |
Client | Memory Layout |
#include <iostream> #include "foo.h" using namespace std; int main() { foo f0; foo f1; foo f2; cout << f0.get_count() << endl; cout << foo::get_count() << endl; return 0; } | ![]() |
(c) | (d) |
static
or class variables allow programmers to save data that applies to all class objects rather than to a particular object. - Programmers create class objects with the
static
keyword. Programs can't accessstatic
variables through athis
pointer because they don't belong to a particular object. So, programmers typically includestatic
functions in the class. - Programmers define and initialize
static
variables outside of classes and member functions. Doing this makes them look like dreaded global variables, but their access is still hidden from other parts of the program by binding the variable name to a class and making itprivate
. - Although we can call a
static
function through an object, for examplef2.get_count()
, most object-oriented programmers consider using the class name with the scope resolution operator a better practice. Doing this also works if all the objects have been destroyed. - Memory for
static
variables is allocated outside of all objects, which means that the variable exists before any objects are instantiated and persists after all objects are destroyed.
Class Constants
We've already seen three ways of creating symbolic or named constants, including using the const
keyword. Each technique creates global constants or names that can be visible anywhere in a program. But is that a significant problem? Linguists estimate that there are more than a million words in the English language and likely similar numbers in other languages. So, it seems like we should be able to write a program without running out of identifier names. For example, more than 456,000 four-characters patterns, nearly half the number of words in the language, can be created using English's 26-character alphabet, but most of those patterns are meaningless. And even so, programmers may want to give the same name to similar functions, variables, or constants defined in different contexts. I encountered this name-collision problem as a C programmer using libraries created by diverse vendors.
Class constants are a special case of class variables, so the solution follows an already established pattern. The stack class created previously included a symbolic constant named SIZE, which was created inside the class using two keywords: static
and const
. const
means that the value cannot change, and static
expands the "ownership" from a particular object to the whole class.
Class Specification | Object Instantiation | Memory Layout |
---|---|---|
class stack { private: char st[SIZE]; int sp; public: static const int SIZE = 100; int size() { return sp; } }; | stack r; stack s; stack t; | ![]() |
(a) | (b) | (c) |
- Non-static fields or variables (e.g., st and sp) "belong" to an instance of the class (i.e., to an object). Conversely, static fields (e.g.,
SIZE ) "belong" to the class as a whole. Together,static
andconst
form a class constant - a symbolic constant defined in the scope of a particular class.static
withoutconst
creates a class variable - a variable shared by all instances of a class, but whose stored value can change. - A C++ program allocates memory for non-static variables whenever a new object is instantiated, and that memory remains associated with that object until the object is destroyed.
- A C++ program allocates memory for static variables when the program is first loaded into main memory to run, and does not deallocate that memory until the program ends. The memory for non-static fields resides inside an object; the memory for
static
fields resides outside of all objects and so exits independently of any instance of the class.
Allowed | Preferred |
---|---|
if (r.size() < r.SIZE) . . . | if (r.size() < stack::SIZE) . . . |
(a) | (b) |
const
and static
keywords make it easy for the client to access the constant. - C++ allows access to class constants through any instance (i.e., object) of the class (highlighted).
- The preferred notation (highlighted) accesses class constants through the class name with the scope resolution operator.
class_name::field_name
is only valid when used with static
data, making the second statement preferred because it conveys to the reader the additional information that SIZE
is a stack class constant. static Functions
I attended an object-oriented conference in early 1990 when the paradigm was gaining popularity. During a two-hour "discussion" (a polite term for a verbal brawl), participants debated the relative merits of extracting data from an object and passing it to a function or just passing the whole object. In frustration, one participant observed, "Taking the liver out of a gorilla is messy and annoys the hell out of the gorilla!" By the end of the "discussion," the consensus was that encapsulation was a critical part of the object-oriented paradigm and worth preserving: Pass the gorilla and let it use its liver on our behalf.
When programs pass objects to member functions, they can pass them as explicit arguments, (appearing between the parentheses of the argument list) or as an implicit argument (see Objects and member functions). Function are bound to and access the member variables of an object through the this
pointer (see this binds objects to member functions). But static
functions do not have a this
pointer, so they can't be bound to an object. That means that static
functions cannot access any non-static feature - they cannot access non-static variables and they cannot call non-static functions.
class alpha { public: static int function(int x) {...} }; | alpha::function(25); |
(a) | (b) |
class beta { public: string to_string(int value) { return std:: to_string(value); } }; | namespace std { string to_string(int value); }; |
(c) | (d) |
- An example of a
static
function. -
static
functions are accessed with the name of the class and the scope resolution operator (in red). - The to_string function represents a more complex scoping problem. Class beta defines a to_string member function that calls the C++
string
class to_string function (see Figure 3). Programmers use the scope resolution operator to resolve the ambiguous use of the to_string(int) function name. - C++ declares the common or standard C++ library functions in the std namespace, and programs can usually access them without ambiguity just by adding the "using" statement at the beginning of a file.
Source: https://icarus.cs.weber.edu/~dab/cs1410/textbook/9.Classes_And_Objects/static.html
Posted by: clintonclintontycere0302089.blogspot.com
Comments
Post a Comment