Урок 124. Статические переменные-члены класса

   ⁄ 

 Обновлено 15 Мар 2018  ⁄ 

⁄   523

Из урока 51 мы узнали, что статические переменные сохраняют свои значения и не уничтожаются даже после выхода из блока, в котором они объявлены. Например:

Результат:

1
2
3

Обратите внимание, s_id сохраняет свое значение после каждого вызова generateID().

Ключевое слово static имеет другое значение, когда речь идет о глобальных переменных — оно дает им внутреннюю связь (что ограничивает их видимость/использование за пределами файла, в котором они определены). Поскольку использование глобальных переменных – это зло, то ключевое слово static в этом контексте не очень часто используется.

Статические переменные-члены класса

В C++ ключевое слово static можно использовать в классах: статические переменные-члены и статические методы. Мы поговорим о статических переменных-членах в этом уроке и о статических методах в следующем.

Прежде чем мы перейдем к ключевому слову static с переменными-членами класса, давайте сначала рассмотрим следующий класс:

При создании объекта класса, каждый объект получает свою собственную копию всех переменных-членов класса. В этом случае, поскольку мы объявили два объекта класса Anything, у нас будет две копии m_value: first.m_value и second.m_value. first.m_value отличается от second.m_value. Следовательно, результат программы выше:



4
3

Переменные-члены класса можно сделать статическими, используя ключевое слово static. В отличие от обычных переменных-членов статические переменные-члены являются общими для всех объектов класса. Рассмотрим следующую программу:

Результат:

4
4

Поскольку s_value является статической переменной-членом, то она является общей для всех объектов класса Anything. Следовательно, first.s_value — это та же переменная, что и second.s_value. Программа выше показывает, что к значению, которое мы установили через первый объект, можно получить доступ и через второй объект.

Статические члены не связаны с объектами класса

Хотя вы можете получить доступ к статическим членам через разные объекты класса (как в примере выше), но, оказывается, статические члены существуют, даже если объекты класса не созданы! Подобно глобальным переменным, они создаются при запуске программы и уничтожаются, когда программа завершает своё выполнение.

Следовательно, статические члены принадлежат классу, а не объектам этого класса. Поскольку s_value существует независимо от любых объектов класса, то доступ к нему осуществляется напрямую через имя класса и оператор разрешения области видимости (в данном случае, Anything::s_value):

В фрагменте выше, доступ к s_value осуществляется через имя класса, а не через объект этого класса. Обратите внимание, мы даже не создавали объект класса Anything, но мы все равно имеем доступ к Anything::s_value и можем использовать этот член.

Определение и инициализация статических переменных-членов класса

Когда мы объявляем статическую переменную-член внутри класса, то мы сообщаем компилятору о существовании статической переменной-члена, но не об её определении (аналогия — предварительное объявление). Поскольку статические переменные-члены не являются частью отдельных объектов класса (они обрабатываются аналогично глобальным переменным и инициализируются при запуске программы), то вы должны явно определить статический член вне класса, в глобальной области видимости.

В программе выше это делается строчкой:

Здесь мы определили статическую переменную-член класса и инициализировали её значением 3. Если же инициализатор не предоставлен, то C++ инициализирует s_value значением 0.

Обратите внимание, это определение статического члена не подпадает под действия спецификаторов доступа: вы можете определить и инициализировать s_value, даже если оно будет private (или protected).

Если класс определен в файле .h, то определение статического члена обычно помещается в файл с кодом класса (например, Anything.cpp). Если класс определен в файле .cpp, то определение статического члена обычно пишется непосредственно под классом. Не пишите определение статического члена класса в заголовочном файле (подобно глобальным переменным). Если этот заголовочный файл подключают больше одного раза, то вы получите несколько определений этого члена, что приведет к ошибке компиляции.

Инициализация статических переменных-членов внутри класса

Есть несколько обходных путей определения статических членов внутри класса. Во-первых, если статический член является константным интегральным типом (к которому относятся и char, и bool) или константным перечислением, то статический член может быть инициализирован внутри класса:

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

Во-вторых, с C++11 статические члены constexpr любого типа данных, поддерживающие инициализацию constexpr, могут быть инициализированы внутри класса:



Использование статических переменных-членов

Зачем использовать статические переменные внутри классов? Для присваивания уникального идентификатора каждому объекту класса (как вариант):

Результат:

1
2
3

Поскольку s_idGenerator является общим для всех объектов класса Anything, то при создании нового объекта Anything, конструктор захватывает текущее значение s_idGenerator, а затем увеличивает его для следующего объекта. Это гарантирует уникальность идентификаторов для каждого созданного объекта класса Anything.

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

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (4 оценок, среднее: 5,00 из 5)
Загрузка...
Подписаться на обновления:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

ПОДПИСЫВАЙТЕСЬ

НА КАНАЛ RAVESLI В TELEGRAM

@ravesli

ПОДПИСАТЬСЯ БЕСПЛАТНО