В чем разница между ключевым словом static в C и C++?

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

Ответ

Ключевое слово static в C и C++ имеет общие и различные значения.

Общие для C и C++ значения:

  1. Static для локальных переменных внутри функции: Переменная сохраняет свое значение между вызовами функции. Инициализируется только при первом вызове.
    void counter() {
        static int count = 0; // Инициализация один раз
        ++count;
        std::cout << "Called " << count << " timesn";
    }
  2. Static для глобальных переменных и функций на уровне файла (модуля): Ограничивает область видимости (linkage) внутренним связыванием (internal linkage). Сущность становится невидимой для других единиц трансляции (.cpp файлов).
    // В file1.cpp
    static int hiddenVar = 42; // Не видна в file2.cpp
    static void helper() {} // Не видна в file2.cpp

Уникальное для C++ значение:

  1. Static члены класса (поля и методы): Член класса, принадлежащий не каждому объекту, а самому классу в целом. Существует в единственном экземпляре для всего класса.

    • Статическое поле: Разделяемая всеми объектами класса переменная. Должно быть определено (и часто инициализировано) вне класса.
    • Статический метод: Функция, не имеющая доступа к указателю this (не может работать с нестатическими полями и методами без передачи объекта). Вызывается через имя класса.
    class Logger {
        static int messageCount; // Объявление статического поля
        std::string instanceName;
    public:
        Logger(const std::string& name) : instanceName(name) {}
        void log(const std::string& msg) {
            ++messageCount; // Обращение к статическому полю
            std::cout << '[' << instanceName << "]: " << msg << 'n';
        }
        // Статический метод
        static int getTotalMessages() {
            // return instanceName.size(); // ОШИБКА: нет доступа к нестатическим членам
            return messageCount;
        }
    };
    
    // Определение и инициализация статического поля ВНЕ класса
    int Logger::messageCount = 0;
    
    int main() {
        Logger logger1("App");
        Logger logger2("Net");
        logger1.log("Hello");
        logger2.log("World");
        // Вызов статического метода через класс
        std::cout << "Total logs: " << Logger::getTotalMessages() << std::endl; // Выведет 2
    }

    Итог: C++ унаследовал все значения static из C и добавил новое, связанное с членами классов, что является фундаментальной частью объектно-ориентированного дизайна.