Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции / Лекция 3-4n.docx
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
74.69 Кб
Скачать

Предупреждение о классах со всеми статическими членами

Будьте осторожны при написании классов со всеми статическими членами. Хотя такие «чисто статические классы» могут быть полезны, но они также имеют свои недостатки.

Во-первых, поскольку все статические члены создаются только один раз, то несколько копий «чисто статического класса» быть не может (без клонирования класса и его дальнейшего переименования).

Например, если нам нужны два независимых объекта класса IDGenerator, то это будет невозможно через «чисто статический» класс.

Во-вторых, о глобальных переменных мы знаем, что глобальные переменные опасны, поскольку любая часть кода может изменить их значения и, в конечном итоге, изменит другие фрагменты, казалось бы, не связанного с этими переменными кода. (детально см. здесь).

То же самое справедливо и для «чисто статических» классов. Поскольку все члены принадлежат классу (а не его объектам), а классы имеют глобальную область видимости, то в «чисто статическом классе» мы объявляем глобальные функции и переменные со всеми минусами, которые они имеют.

C++ не поддерживает статические конструкторы

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

И, хотя некоторые современные языки программирования действительно поддерживают использование статических конструкторов именно для этой цели, язык C++ не является одним из таковых.

Если ваша статическая переменная может быть инициализирована напрямую, то конструктор не нужен: вы можете определить статическую переменную-член, даже если она является private.

Мы делали это в вышеприведенном примере с s_nextID. Вот еще один пример:

class Something {

public:

static std::vector<char> s_mychars;

};

// определяем статическую переменную-член

std::vector<char> Something::s_mychars = { 'o', 'a', 'u', 'i', 'e' };

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

#include <iostream>

#include <vector>

class Something {

private:

static std::vector<char> s_mychars;

public:

class _nested { // определяем вложенный класс с именем

//_nested

public:

_nested () { // конструктор _nested () инициализирует нашу

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

s_mychars.push_back('o');

s_mychars.push_back('a');

s_mychars.push_back('u');

s_mychars.push_back('i');

s_mychars.push_back('e');

}

};

// Статический метод для вывода s_mychars

static void getSomething() {

for (auto const &element: s_mychars)

std::cout << element << ' ';

}

private:

static _nested s_initializer; // используем статический объект //класса _nested для гарантии того, что конструктор _nested() выполнится

};

std::vector<char> Something::s_mychars; // определяем нашу статическую переменную-член

Something::_nested Something::s_initializer; // определяем наш //статический s_initializer, который вызовет конструктор _nested() для //инициализации s_mychars