Неразрешенный внешний символ для статических членов класса

Очень просто:

У меня есть класс, который состоит в основном из статических открытых членов, поэтому я могу сгруппировать похожие функции, которые все еще должны вызываться из других классов/функций.

В любом случае, я определил две статические переменные типа unsigned char в общедоступной области видимости. Когда я пытаюсь изменить эти значения в конструкторе того же класса, я получаю ошибку "неразрешенный внешний символ" при компиляции.

class test 
{
public:
    static unsigned char X;
    static unsigned char Y;

    ...

    test();
};

test::test() 
{
    X = 1;
    Y = 2;
}

Я новичок в C++, так что будь осторожен со мной. Почему я не могу это сделать?

Ответ 1

Вы забыли добавить определения в соответствии с вашими объявлениями X и Y

unsigned char test::X;
unsigned char test::Y;

где-то. Возможно, вы захотите также инициализировать статический член

unsigned char test::X = 4;

и снова, вы делаете это в определении (обычно в файле CXX) не в объявлении (которое часто находится в файле .H)

Ответ 2

Объявления статических данных в объявлении класса не являются их определением. Чтобы определить их, вы должны сделать это в файле .CPP, чтобы избежать дублирования символов.

Единственными данными, которые вы можете объявить и определить, являются интегральные статические константы. (Значения enums также могут использоваться как постоянные значения)

Возможно, вы захотите переписать код следующим образом:

class test {
public:
  const static unsigned char X = 1;
  const static unsigned char Y = 2;
  ...
  test();
};

test::test() {
}

Если вы хотите иметь возможность изменять статические переменные (другими словами, если нецелесообразно объявлять их как const), вы можете отделить код между .H и .CPP следующим образом:

.H:

class test {
public:

  static unsigned char X;
  static unsigned char Y;

  ...

  test();
};

.CPP:

unsigned char test::X = 1;
unsigned char test::Y = 2;

test::test()
{
  // constructor is empty.
  // We don't initialize static data member here, 
  // because static data initialization will happen on every constructor call.
}

Ответ 3

Так как это первый SO поток, который мне показался при поиске "неразрешенных внешних элементов со статическими константными членами" в общем, я оставлю еще одну подсказку, чтобы решить одну проблему с неразрешенными внешними объектами:

Для меня вещь, которую я забыл, состояла в том, чтобы пометить определение моего класса __declspec(dllexport), и при вызове из другого класса (за пределами этого класса dll) я, конечно, получил свою неразрешенную внешнюю ошибку.
Тем не менее, легко забыть, когда вы меняете внутренний вспомогательный класс на класс, доступный из других источников, поэтому, если вы работаете в динамически связанном проекте, вы также можете проверить это.

Ответ 4

в моем случае я объявил одну статическую переменную в файле .h, например,

//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}

и в myClass.cpp я попытался использовать этот m_nMyVar. Он получил ошибку ССЫЛКИ, как:

ошибка LNK2001: неразрешенный внешний символ "public: static class... Файл cpp, связанный с ошибкой ссылки, выглядит следующим образом:

//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

Поэтому я добавляю код ниже в верхней части myClass.cpp

//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

тогда LNK2001 ушел.