Вы находитесь на странице: 1из 19

Александр Загоруйко © 2020

Static context
Представим ситуацию
class Person {
char* name;
};

class Kitchen {
char* fridge = "empty";
};

class Flat { // каждый экземпляр класса


Person* residents; // Flat будет содержать свои
Kitchen kitchen; // копии полей residents и
}; // kitchen.
Общее поле
А что, если потребуется такое поле,
которое было бы общим для всех
экземпляров класса?
Другая ситуация
Иногда возникает необходимость
отслеживать количество созданных
экземпляров класса. Например, чтобы на
игровой локации одновременно находилось
не более 10 монстров. Завести переменную
count как обычное поле класса – не вариант,
так как у каждого монстра будет своя
переменная, и организовать механизм
своевременного обновления значения этого
поля для каждого монстра будет просто
нереально… Что же делать? 
Глобальная переменная

Ну вот например, есть такое решение:

https://git.io/vo9c0
Но оно не самое лучшее, так как в ООП
сведено к минимуму использование
глобальных переменных (их наличие
нарушает инкапсуляцию).
Статическое поле

Хорошие новости: есть более


правильный способ сделать поле
общим для всех экземпляров класса –
нужно всего лишь пометить его как
статическое при помощи ключевого
слова static:

https://git.io/vo9ci
Определение
Статическое поле (static data member, static class field, class
variable) — поле, общее для всех объектов класса, и
относящееся непосредственно к самому классу в целом, а
не к его объектам. Статическое поле будет доступным,
даже если ещё не создано ни одного объекта класса!
Такие поля по семантике не отличаются от обычных
глобальных переменных, но они доступны только
по квалифицированному имени (то есть с указанием имени
класса), и поэтому, в отличие от глобальных переменных,
не загромождают пространство глобальных имён.
Cтатические поля  — это самый простой и правильный с
точки зрения ООП способ хранения глобальных данных,
вроде количества созданных объектов.
Выделение памяти под поля
Объявление класса само по себе
места в памяти не занимает –
память будет выделена только при
создании объектов класса. Причём,
в момент создания объекта память
выделяется лишь для нестатических
полей класса, в то время, как
статическое поле будет всего одно
на все объекты этого класса.
Обращение к полю

Поскольку статическое поле не связано


с созданием экземпляров класса, то для
того, чтобы им воспользоваться, вовсе
не нужно создавать такие экземпляры
класса:

// in main:
cout << Monster::count; // if count is public!
// можно и через объект, но не рекомендуется так делать!
Свойства статических полей

 Внутри методов класса префикс,


состоящий из имени класса, можно не
указывать
 Статическое поле напрямую доступно на
чтение и запись из не-статических
методов (но не наоборот!)
 К статическим полям применяются такие
же модификаторы доступа, как и к
экземплярным (не-статическим) полям

https://git.io/vo9CT
Статические методы

Аналогичные соображения формальной


принадлежности к классу возникают и
относительно методов. Иногда
необходима функция, которая не должна
непосредственно работать с
экземплярами класса, но логически
должна быть связана с классом. Для
реализации таких функций используются
статические методы класса.
Инкапсуляция СП
Никто не отменял инкапсуляцию для
статических полей, и оставлять поле count
(счётчик объектов) в открытом доступе –
кощунственно:
https://git.io/vo9CZ
Поскольку статический метод не связан с
созданием экземпляров класса, то для того,
что им воспользоваться, как и в случае с
полями, не нужно создавать экземпляры
класса.
Практика

Пример использования Ст.Методов:


https://git.io/vo9C0

Задание:
Создать класс Sort, который будет
содержать в себе 3 статических метода,
реализующих разные алгоритмы сортировки
одномерных массивов.
Принципиальное отличие!!!
Главное отличие статического и нестатического
методов заключается в том, что, поскольку
статическим методам не нужны экземпляры
класса, то они не получают this, т.е. неявного
параметра, содержащего указатель на
экземпляр класса, для которого вызываются
обычные методы. Это в свою очередь
означает, что внутри статических методов
нельзя обращаться напрямую к не-статическим
полям, т.к. не понятно о полях какого именно
экземпляра класса будет идти речь!
Паттерн Singleton
Существует множество объектов, которые
будут нужны лишь в единственном
экземпляре: пулы потоков, модальные
диалоговые окна, объекты логирования
данных, объекты драйверов устройств…
Более того, попытка создать более одного
подобного экземпляра может привести к
некорректному поведению программы,
лишним затратам ресурсов и нелогичному
результату.
Паттерн Singleton
Паттерн «Одиночка» представляет собой
схему, которая гарантирует, что для
заданного класса может быть создан один
и только один объект, и предоставляет
глобальную точку доступа к этому объекту.
Относится к порождающим паттернам.
Метафора паттерна
Представьте, что в городе требуется организовать связь между жителями.
Например, можно связать всех жителей, протянув между ними кабеля
телефонных линий, однако, такая система не оправдывает себя. Ведь
добавить ещё одного жителя будет очень непросто (придётся протянуть
ещё по одной линии к каждому жителю). Чтобы этого избежать, мы
создаем телефонную станцию, которая и будет нашей «одиночкой». Она
одна, всегда, и если кому-то потребуется связаться с кем-то, то он может
это сделать через данную телефонную станцию, потому что все
обращаются только к ней. Соответственно, для добавления нового
жителя нужно будет изменить только записи на самой телефонной
станции. Один раз создав телефонную станцию, все могут пользоваться
ей и только ей одной, в свою очередь эта станция помнит всё, что с ней
происходило с момента её создания, и каждый может воспользоваться
этой информацией, даже если он только приехал в город.
Основной смысл «одиночки» в том, чтобы когда вы говорите «Мне нужна
телефонная станция», вам бы говорили «Она уже построена там-то», а не
«Давай её сделаем заново».
Классическая реализация

https://git.io/vo9WZ
Пример паттерна Singleton

Реализация логгера:
https://git.io/vo9CN

Вам также может понравиться