TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #133 1.62K
​Определение статических полей класса

Если вы хоть раз пытались наивно инициализировать статический член класса внутри самого класса, то явно знаете, о чем речь пойдет. А для тех, кто не знает, скажу, что произойдет дальше. Компилятор выдаст ошибку типа: ISO C++ forbids in-class initialization of non-const static member. Стандарт запрещает неконстантным статическим полям инициализироваться внутри класса. Ранее стандартной практикой для решения этой проблемы был вынос определения этого поля в цпп файл. Решение довольно неудобное, ибо каждый раз нужно лезть в файл реализации, чтобы посмотреть инициализатор. Да и писать это не очень удобно. В потенциале для такой инициализации нужно дополнительно написать в 1.5 раза больше букав, чем при удобной in-class инициализации. Если это так неудобно, то почему такое правило вообще введено?

Давайте небольшой рекап для статических членов. Статическое поле класса - по сути глобальный объект, который как бы присоединен к классу. Любой объект класса может получить доступ к одному и тому же инстансу статической переменной. Как и любой код, который может создать объект класса, сможет использовать его статический член через имя класса. Типа такого ClassType::static_field. То есть, несмотря на то, что поле объявлено как static, оно имеет внешнее связывание. То есть существует лишь один инстанс этого поля, который виден всему коду, имеющему доступ к классу. И для такой сущности применяется One Definition Rule(ODR), которое говорит, что у переменной или функции(за некоторыми исключениями) внутри ВСЕЙ программы может быть сколько угодно объявлений, но только одно определение. Ща поясню, к чему это приводит.

Вот у вас есть описание класса в каком-то хэдере. Как использовать этот класс? Заинклюдить этот хэдер в нужный файлик. А что делает иклюд? Правильно, на этапе препроцессора он просто заменяется на текст подключаемого файла. Поэтому если у вас определение статического поля находится в хэдере, значит у вас есть определение этого поля во всех единицах трансляции, куда попало описание класса. А это прямое нарушение ODR.

Описания классов обычно находятся в хэдэрах, поэтому проще просто запретить определять статические поля внутри классов.

Как меняет ситуацию определение поля вне класса в цпп файле? Это позволяет не нарушать ODR, все просто) Ну если чуть подробнее, то во всех единицах трансляции, куда мы подключили описание класса, будет только объявление нашего поля. И только одно определение будет браться из нашего цпп файлика.

И кстати в файле реализации нельзя приписывать определению переменной пометку static. Это путает компилятор. Обычно для переменных static значит статическое время жизни и внутреннюю линковку, а нам здесь нужна внешняя линковка.

Это кстати довольно важно подсветить: static для обычных глобальных переменных меняет их тип линковки на внутреннюю, а внутри класса static обозначает внешнюю линковку(что с методами, что с полями).

Но начиная с 17-х плюсов есть намного более изящный способ обойти ODR в этом конкретном случае. Постоянные читатели или просто знающие люди уже понимают, о чем речь. Но пост об этом будет позже)

Define yourself. Stay cool.

#cppcore
  • 🔥 13
  • 👍 9
  • ❤ 4
  • 😢 1
  • 😍 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →