Ответ 1
Чтобы понять это, вы должны хорошо понимать компиляцию и компоновку, а также различия между объявлениями и определениями.
Рассмотрим следующий класс:
//In header file
class Example {
static bool exampleStaticMember;
};
Здесь exampleStaticMember
объявлен, но не определен. Это означает, что если exampleStaticMember
используется таким образом, что это означает, что он должен иметь адрес, то для него должно быть отдельное определение. В общем, никакое объявление статического члена данных в определении класса не является определением этого члена.
Требуемое объявление обычно помещается в файл cpp, который содержит другие определения для членов класса. Он должен находиться в том же пространстве имен, что и определение класса. Определение обычно выглядит следующим образом:
//In source file:
//This may optionally have an initialiser (eg "= true")
bool Example::exampleStaticMember;
Определение может быть помещено в любой файл cpp, но его не следует помещать в заголовок с классом, потому что это может привести к нарушению правила One Definition Rule.
В качестве частного случая, если статическая переменная-член является константным интегральным или перечисляющим типом, то он может иметь инициализатор в определении класса:
//In header file
class Example {
static const int initialised = 15;
};
В этом случае определение в файле cpp по-прежнему требуется, но ему не разрешено иметь инициализатор:
//In source file
//Note: no initialiser!
const int Example::initialised;
Статические элементы, которые были инициализированы таким образом, могут использоваться в постоянных выражениях.
Шаблоны
Для статического элемента данных шаблона все немного отличается. Статический член должен быть определен в заголовке вместе с остальной частью класса:
//In header file
template<typename T>
class Example {
static int exampleInt;
static T exampleT;
}
template<typename T> int Example<T>::exampleInt;
template<typename T> T Example<T>::exampleT;
Это работает, потому что существует конкретное исключение из правила One Definition для статических элементов данных шаблонов классов.
Другие применения статического
Когда ключевое слово static
применяется к функциям и объектам, которые не находятся в области класса, это может иметь совсем другое значение.
При применении к объектам в области функций он объявляет объект, который инициализируется при первом выполнении функции и который впоследствии сохраняет свое значение между вызовами функций.
При применении к объектам или функциям в пространстве пространства имен (за пределами любого определения класса или функции) он объявляет объекты или функции с помощью внутренней связи. Это использование устарело для объектов, так как unnamed-namespace обеспечивает лучшую альтернативу.