- •Глава 12
- •Конструкторы и деструкторы. Список инициализации элементов
- •Конструкторы по умолчанию и конструкторы копирования
- •Указатель this
- •Встраиваемые (inline-) функции
- •Статические члены класса
- •Использование указателей на функции-члены класса
- •Массивы объектов класса
- •Дружественные функции и друзья класса
- •Глава 13
- •Множественное наследование
- •Виртуальные базовые классы
- •Глава 14
- •Перегрузка функций
- •Перегрузка конструкторов
- •Создание и использование конструкторов копирования
- •Определение адреса перегруженной функции
Статические члены класса
Члены класса могут быть объявлены с модификатором static. Статический член класса может рассматриваться как глобальная переменная или функция, доступная только в пределах области класса.
Данное-член класса, определенное с модификатором static, разделяется всеми представителями этого класса, так как на самом деле существует только один экземпляр этой переменной. На самом деле, память под статические данные-члены выделяется, даже если нет никаких представителей класса. Поэтому класс должен не только объявлять статические данные-члены, но и определять их. Например:
class AnyClass
{
public:
AnyClass();
//объявление статического данного-члена
static int count;
};
//определение статического данного-члена
int AnyClass::count = 0;
Заметим, что хотя к статическим данным-членам, объявленным в разделе public класса, можно обращаться с помощью конструкции, использующих имя объекта:
<объект>.<данное_член>
или
<указатель_на_объект>- ><данное_член>,
лучше использовать форму вызова
<имя_класса>: : <данное_член>,
которая является более правильной, так как отражает тот факт, что соответствующее данное-член является единственным для всего класса. Если статические данные-члены объявлены как закрытые, то доступ к ним можно получить с помощью обычных функций-членов. Доступ к статическим данным-членам с помощью обычных функций-членов ничем не отличается от доступа к другим данным-членам, но для этого необходимо создать хотя бы один объект данного класса. В связи со сказанным выше, можно дать следующие рекомендации:
• применяйте статически данные-члены для совместного использования данных несколькими объектами класса;
• ограничьте доступ к статическим данным-членам, объявив их в разделе protected или private.
Рассмотрим пример использования статического данного-члена класса:
#include <iostream.h>
class T
{
public:
T(){ObCount++;}
~T(){ObCount--;}
static int ObCount;
//...
private:
int x;
};
int Т::ObCount = 0;
int main()
{
T* pOb = new Т[5];
cout « " Имеется " « Т::ObCount « " объектов типа Т\n";
delete[] рОb;
return 0;
}
В этом примере статическое данное-член просто ведет учет созданных объектов. При выполнении программа выводит на экран:
Имеется 5 объектов типа Т
Особенностью использования статических функций-членов является то, что они также определены в единственном экземпляре и не являются безраздельной собственностью какого-то представителя класса. В связи с этим им не передается указатель this. Эта особенность статических функций-членов используется при написании функций-обработчиков прерывании и callback-функций (при программировании для Windows).
Из сказанного выше вытекает несколько важных следствий:
• статическая функция-член может вызываться независимо от того, существует или нет какой-либо представитель класса;
• статическая функция-член может манипулировать только статическими данными-членами класса и вызывать только другие статические функции-члены класса;
• статическая функция-член не может быть объявлена с модификатором virtual.
Приведем пример использования статической функции-члена. Он представляет собой слегка отредактированный предыдущий пример:
#include <iostream.h>
class T
{
public:
Т(){ObCount++;}
~Т(){ObCount--;}
//...
static int GetCounts(){return ObCount;}
private:
int x;
static int ObCount;
};
int Т::ObCount = 0;
int main ()
{
Т* рОb = new Т[5] ;
cout « "Имеется " « Т::GetCounts() « " объектов типа Т\n";
delete[] pOb;
return 0;
}
Константные объекты и константные функции-члены класса.
Ключевое слово mutable
Функция-член класса может быть объявлена с модификатором const, который следует за списком параметров. Такая функция не может изменять значение данных-членов класса и не может вызывать не константные функции-члены класса. Приведем пример объявления константной функции-члена класса:
class Coord
{
int х,у;
public:
Coord(int _x, int _y);
void SetVal(int _x, int _y);
//константна функция-член
void GetVal(int_x, int_y) const;
};
Можно также создавать константные объекты. Для этого их объявления предваряют модификатором const. Например,
const Coord ob(3,5);
Ключевое слово const информирует компилятор, что состояние данного объекта не должно изменяться. В связи с этим компилятор генерирует сообщение об ошибке, если для константного объекта вызывается функция-член (которая может изменить его данные-члены, изменив тем самым его состояние). Исключением из этого правила являются константные функции-члены, которые в силу своего определения не изменяют состояние объекта. Приведем пример:
class Coord
{
int х, у;
public:
Coord(int _x, int _y);
void SetVal(int _x, int _y);
void GetVal(int &_x, int &_y) const;
};
Coord::Coord(int _x, int _y)
{
x = _x;
у = _y;
}
void
Coord::SetVal(int _x, int _y)
{
x = _x;
у = _y;
}
//Константная функция-член
void
Coord::GetVal(int &_x, int &_y) const
{
_x = x;
_y = y;
}
int main()
{
Coord ptl(3,8);
const Coord pt(6,9) ; //Константный объект
int x, у;
ptl.GetVal(x,y);
//Ошибка.. Вызов не-константной функция-члена
pt2. SetVal (x, у);
pt2.GetVal(x, у);
return 0;
}
Чтобы обойти указанные выше ограничения на использование константных функций-членов класса, в стандарт языка C++ было введено новое ключевое слово mutable. Это ключевое слово позволяет указать, какие данные-члены класса могут быть модифицированы константными функциями-членами. Ключевое слово mutable нельзя использовать для статических и константных членов-данных; оно используется как модификатор типа, то есть синтаксис его использования имеет вид:
mutable <тип_данных> <имя_переменной-члена>;
Приведем пример использования ключевого слова mutable:
#include <iostream.h>
class AnyClass
{
mutable int count;
mutable const int* iptr;
public:
int func(int i=0) const
{
count = i++;
iptr = &i;
cout « iptr;
return count;
}
};
Здесь в операторе
mutable const int* iptr;
модификатор mutable допустим, так как iptr является указателем на целое число, которое есть константа, хотя сам указатель константой не является.
