1. Статични променливи на класа (Static Member Data). Досега използвахме само променливи, които имат различни стойности за всеки един обект от този клас. Но в много приложения е необходимо да има променливи, които са с една и съща стойност за всички обекти. Нека си представим, например, моделирането на състезателна игра с коли и един от класовете е състезателната кола. Скоростта, количеството гориво и степента на повреда са конкретни променливи на всеки един обект състезателна кола, но дължината на пистата или препятствията по нея (които са еднакви за всички коли) са променливи, които не само имат една и съща стойност, но и трябва да са достъпни за всички обекти от класа. Разбира се, можем да ги моделираме като външни променливи, но както споменахме този подход има своите затруднения и се избягва в ООП, още повече че има статични променливи на класа.
2. Създаване на статични променливи на класа (Creating Static Data). Синтактисът за създаване на такива данни е донякъде необичаен, защото първо в класа се пише декларация на променливата, а извън класа тя се дефинира. Например
class
aclass
{
private:
static int stavar; // declaration
// other declarations & definition in the class
};
int aclass::stavar = 77; // definition
Декларацията използва ключовата дума static. Дефиницията използва името на класа и оператора за решение за обхвата (scope resolution operator), :: , въведен в лекция 24 (той там бе използван за функции на класа, дефинирани извън класа). В примера по-горе променливата stavar е инициализирана, но ако не беше тя щеше да получи по подразбиране стойност 0 (съответно 0.0 за реалните променливи). Веднъж дефинирана статичната променлива може да бъде достъпна само от функциите на класа, т.е. нейният обхват е класа.
3. Достъп до статични променливи на класа (Accessing Static Data). Както споменахме всяка една функция на класа има достъп до статичните променливи на същия клас, но е по-уместно да се създаде специална функция, която има достъп до дадена статична променлива (или няколко статични променливи). Т.е. опираме до т.н. статични функции на класа (static functions). Такава функция е задължително необходима ако искаме да предадем стойността на статичната променлива на променлива извън класа или на променлива на друг обект (вижте примера от т. 4).
Статичната функция на класа също се дефинира с ключовата дума static и изглежда като обичайна функция на класа, но тя се извиква не от конкретен обект на класа, а с името на класа, последвано от оператора за решение за обхвата (scope resolution operator), :: . Ето един схематичен пример
class
aclass
{
private:
// decalations & definitions
public:
static int stafunc() // function definition
{
// can access only static member data
}
};
main()
{
// other statments
aclass::stafunc(); // function call
// other statments
}
Статичната функция на класа не може да се обръща към нестатичните променливи на класа - това е очевидно от това, че се извиква с името на класа (в горния пример aclass::stafunc();). Също така тези функции могат да се извикват преди да е създаден обект от класа.
4. Пример за броене на обектите (Count-the-Objects Example). Това е пример от книгата на Лафоор [1]. Програмата създава клас widget (джаджа). Всяка джаджа има сериен номер, стартиращ от 10,000. Статичната променлива total_widgets държи сметка колко обекта са създадени - тя се променя във функцията на класа init(). В тази функция първо става присвояване към серийния номер на стойност 10,000 плюс броя джаджи (т.е. първата има номер 10,000), а после се увеличава статичната променлива total_widgets: забележете че операторът ++ е постфиксен оператор (postfix operator).
//
static.cpp
//
demonstrates static data and functions
#include
<iostream.h>
#include
<conio.h>
using
namespace std;
////////////////////////////////////////////////////////////////
class
widget
{
private:
int widget_number;
// a widget's serial number
static int total_widgets; // all widgets made so far
// NOTE: declaration only
public:
void init()
// initialize one widget
{
widget_number = 10000 + total_widgets++;
}
int get_number()
// get a widget's number
{
return widget_number;
}
static int get_total() // get total widgets
{
return total_widgets;
}
};
// class widget
int widget::total_widgets = 0; // NOTE: definition
void
main()
{
cout << "Total widgets = " << widget::get_total() <<
endl;
widget w1, w2, w3; // create widgets
w1.init();
// initialize them
w2.init();
w3.init();
cout << "w1 = " << w1.get_number() << endl;
cout << "w2 = " << w2.get_number() << endl;
cout << "w3 = " << w3.get_number() << endl;
cout << "Total widgets = " << widget::get_total() <<
endl;
// added to stop the screen
getch();
}
Статичната функция се извиква не с конкретен обект, а с името на класа: widget::get_total(). Изпълнението на тази програма дава следното на екрана
Total
widgets = 0
w1
= 10000
w2
= 10001
w3
= 10002
Total
widgets = 3
Ако главната функция я изменим по този начин (т.е. да следим броя на джаджите след всяко извикване на init())
void
main()
{
cout << "Total widgets = " << widget::get_total() <<
endl;
widget w1, w2, w3; // create widgets
w1.init();
// initialize them
cout << "Total widgets = " << widget::get_total() <<
endl;
w2.init();
cout << "Total widgets = " << widget::get_total() <<
endl;
w3.init();
cout << "Total widgets = " << widget::get_total() <<
endl;
cout << "w1 = " << w1.get_number() << endl;
cout << "w2 = " << w2.get_number() << endl;
cout << "w3 = " << w3.get_number() << endl;
// added to stop the screen
getch();
изходът на екрана ще е следният
Total
widgets = 0
Total
widgets = 1
Total
widgets = 2
Total
widgets = 3
w1
= 10000
w2
= 10001
w3
= 10002
Обърнете внимание, че и в двата варианта на главната функция статичната функция се извиква преди още да са създадени обекти от класа с твърдението
widget w1, w2, w3; // create widgets
В тази програма статичната променлива total_widgets е използвана във функцията init(), но както ще видим в следващите лекции това е по-добре да се направи в конструктура на класа.
Keywords: С++,
OOP programming , C++ , Classes , Inheritance , Reusability , Creating
New Data Types , Polymorphism and Overloading
Ключови думи: клас
, обект, обектно ориентирано програмиране , полиморфизъм switch if else
?