Для чего нужно ключевое слово static в C++?

«Для чего нужно ключевое слово static в C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово static в C++ имеет четыре различных значения в зависимости от контекста:

1. Статические локальные переменные (внутри функций)

void counter() {
    static int count = 0; // Инициализируется ОДИН раз при первом вызове
    count++;
    std::cout << "Вызов №" << count << std::endl;
}

int main() {
    counter(); // Вызов №1
    counter(); // Вызов №2
    counter(); // Вызов №3
    // Переменная count сохраняет значение между вызовами
}

2. Статические члены класса

class Logger {
private:
    static int instanceCount; // Объявление - общая для всех объектов

public:
    Logger() {
        instanceCount++; // Увеличиваем общий счётчик
    }

    static int getInstanceCount() { // Статический метод
        return instanceCount; // Работает без объекта
    }

    static void setLogLevel(int level) { // Ещё один статический метод
        // Может обращаться только к статическим полям
    }
};

// Определение статического члена (ОБЯЗАТЕЛЬНО в .cpp файле)
int Logger::instanceCount = 0;

int main() {
    Logger logger1, logger2, logger3;
    std::cout << Logger::getInstanceCount(); // 3 - вызов без объекта
}

3. Статические функции и переменные в области видимости файла

// file1.cpp
static int internalVariable = 42; // Видна ТОЛЬКО в этом файле
static void internalFunction() {   // Видна ТОЛЬКО в этом файле
    // ...
}

// file2.cpp
extern int internalVariable; // ОШИБКА линковки - не найдена

4. Статические члены в шаблонах

template<typename T>
class TypeTracker {
public:
    static int creationCount; // Каждая специализация имеет свою копию
};

// Определение для каждой специализации:
template<typename T>
int TypeTracker<T>::creationCount = 0;

int main() {
    TypeTracker<int>::creationCount++;
    TypeTracker<double>::creationCount++;
    // TypeTracker<int>::creationCount и TypeTracker<double>::creationCount - РАЗНЫЕ переменные
}

Ключевые различия:

  • Время жизни: статические переменные живут всю программу (как глобальные)
  • Область видимости: ограничена в зависимости от контекста
  • Память: статические члены класса не увеличивают размер каждого объекта