Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа №4,№5.pdf
Скачиваний:
105
Добавлен:
11.02.2015
Размер:
1.13 Mб
Скачать

Основы создания программ в Си

Page 49 of 58

Операция [ ] (как и операция присваивания) обязана возвращать ссылку, поскольку выражение «имя[индекс]» может находиться как справа, так и слева от операции присваивания.

Тип индекса может не совпадать с типом возвращаемой ссылки; тип возвращаемой ссылки не обязательно должен быть типом определяемого класса; тип индекса не обязан быть целочисленным.

Обычно реализуют два метода: константный и неконстантный.

тип_1& operator[ ](const тип_2 &index)

const тил_1& operator[ ](const тип_2 &index) const

Неконстантный метод работает, когда выражение «имя[индекс]» стоит слева от знака операции присваивания. Константный метод вызывается, например, для параметров, передаваемых по константной ссылке.

Статические элементы класса

Помимо целочисленных констант, в классе разрешается объявлять константные и неконстантные статические поля любых типов (в том числе и статические массивы), а также статические методы.

Статическое поле «является частью класса, но не является частью объекта этого класса». Статические поля класса создаются в единственном экземпляре независимо от количества определяемых в программе объектов. Все объекты (даже созданные динамически) разделяют единственную копию статических полей. При этом в класс включается только объявление, а определение статического поля записывается за пределами класса. Статические поля нельзя инициализировать в конструкторе, так как они создаются до создания любого объекта. Для объявления поля статическим нужно помимо типа и «константности» указать слово static:

static тип имя;

static const тип имя;

Аналогично объявляется и статический массив:

static тип имя[количество]; static const тип имя[количество]; static тип иия[ ];

static const тип имя [ ];

Определение статических полей выполняется вне класса:

тип класс::имя;

тип класс::имя = инициализатор; const тип класс::имя = инициализатор;

Основы создания программ в Си

Page 50 of 58

тип класс::иия[количество];

тип класс::имя[количество] = инициализатор; const тип класс::имя[количество] = инициализатор;

тип класс::имя[] = инициализатор; const тип класс::имя[] = инициализатор;

Слово static в определении писать нельзя. При определении поля выполняется и его инициализация. Если статическое поле является константным, инициализация обязательна. Для неконстантных полей элементарных типов при отсутствии явной инициализации выполняется обнуление. Для статических полей неэлементарных типов вызываются конструкторы: либо явным образом конструктор инициализации, либо, при отсутствии явной инициализации, конструктор по умолчанию. Для константного статического массива или для статического массива без заданного количества элементов инициализация обязательна (см. пример 5.6).

Определение должно быть единственным в программе, иначе компоновщик (не компилятор) сообщит о повторном определении. Если определение отсутствует, тоже возникает ошибка компоновки. Принцип инкапсуляции соблюдается — доступ к таким полям имеют только методы и «друзья» класса.

Статический метод тоже является методом класса; он не может быть ни константным, ни виртуальным; в статическом методе нельзя вызывать виртуальные методы. Ни конструкторы, ни деструктор, ни операция присваивания не могут быть статическими.

Объявление статического метода отличается от объявления обычного метода словом static перед заголовком:

static тип имя(параметры);

// статический метод

Определение вне класса записывается обычным образом без слова static:

тип класс::имя(параиетры)

{ /* тело статического метода */ }

Статические методы вправе обращаться только к статическим полям класса. Статический метод разрешено вызывать для конкретного объекта, как и любой другой метод класса. Статический метод можно вызывать как метод класса независимо от определения объектов — в этом случае вызов пишется с префиксом класса. Так как статический метод не «приписан» к объекту, он не получает указателя this в качестве параметра.

Любые статические элементы могут быть объявлены во вложенных классах.

Несмотря на то что поля объявлены приватными, значения им присваиваются «в открытую». Такая инициализация разрешена только в определении, которое обязан предоставить создатель класса, иначе программа не пройдет компоновку.

Определение единственное, поэтому механизм защиты данных работает по-прежнему — присвоить значение приватной статической переменной «в открытую» в другом месте невозможно.

Основы создания программ в Си

Page 51 of 58

Пример 5.6: Статические поля в классе

Содержимое для *.h файла:

#include <string> using namespace std;

#pragma once

class Programmer

{

std::string Fio; // неэлементарный тип int year;

public:

// конструктор по умолчанию

Programmer(void):Fio("Listkov"), year(1948) {}; Programmer(std::string fio, int y) // конструктор инициализации

{

Fio = fio; year = y;

};

~Programmer(void);

};

 

class StaticField

// неэлементарный тип

{

 

static const int s01 = 1;

// инициализированная константа

static const int s02;

// неинициализированное константное поле

static const double s03;

// константное поле не целого типа

static int s04;

// неконстантное поле целого типа

static double s05;

// неконстантное поле не целого типа II

static const Programmer p;

//константное поле неэлементарного типа

static Programmer t;

// неконстантное поле неэлем-го типа

static int m01[];

// статический неконстантный массив

static const double m02[];

// статический константный массив

static void print();

// статический метод

};

 

Содержимое для *.cpp файла:

// определение статического метода void StaticField::print()

Основы создания программ в Си

Page 52 of 58

 

 

 

{ /* вывод статических полей класса */ }

// определение статических полей const int StaticField::s02 = 2; const double StaticField::s03 = 3.1; int StaticField::s04;

double StaticField::s05;

const Programmer StaticField::p("Kupaev", 1978);

Programmer StaticField::t;

int StaticField::m01[] = {1,2,3};

const double StaticField::m02[] = {2.718281828, 3.141592653};

Несмотря на то что поля объявлены приватными, значения им присваиваются «в открытую». Такая инициализация разрешена только в определении, которое обязан предоставить создатель класса, иначе программа не пройдет компоновку. Определение единственное, поэтому механизм защиты данных работает по-прежнему — присвоить значение приватной статической переменной «в открытую» в другом месте невозможно.

Подсчет объектов класса

Классическое применение статических полей — подсчет объектов. Для этого в классе объявляется статическое поле целого типа, которое увеличивается в конструкторе, а уменьшается в деструкторе (см. пример 5.7).

Пример 5.7 Подсчет объектов класса:

class Object

{

static unsigned int m_count; // статическое поле - счетчик public:

Object();

~Object();

static unsigned int Count(); // выдача счетчика

};

unsigned int Object::m_count = 0;

Object::Object()

{ ++m_count; } // увеличение счетчика при создании

Object::~Object()