Подтвердить что ты не робот

Что значит иметь ссылку undefined на статический член?

Я просто написал класс с некоторыми статическими элементами данных, но теперь я получаю ошибки в отношении "undefined ссылок". Почему это не работает? Что я делаю неправильно?

<суб > (Примечание: это означает запись в Часто задаваемые вопросы о переполнении стека С++. Если вы хотите критиковать идею предоставления FAQ в этой форме, тогда публикация на мета, которая начала все это, была бы местом для этого. Ответы на этот вопрос отслеживаются в С++ чате, где идея FAQ начиналась в первую очередь, поэтому ваш ответ, скорее всего, будет прочитан теми, кто придумал эту идею.) Суб >

4b9b3361

Ответ 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 обеспечивает лучшую альтернативу.

Ответ 2

Вам нужно создать статические элементы, определенные в заголовке в файле .cpp. Например:

// foo.h

class foo {
    static int X;
};


// foo.cpp

#include "foo.h"

int foo::X = 0;