Нерозв’язаний зовнішній символ на статичних членах класу


129

Дуже просто кажучи:

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

У будь-якому випадку, я визначив дві статичні неподписані змінні char у загальнодоступній області мого класу, коли я намагаюся змінити ці значення в конструкторі одного класу, я отримую помилку "невирішений зовнішній символ" при компіляції.

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

    ...

    test();
};

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

Я новачок у С ++, так що просто на мене. Чому я не можу цього зробити?

Відповіді:


145

Ви забули додати визначення, які відповідають вашим деклараціям X і Y

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

десь. Ви також можете ініціалізувати статичний член

unsigned char test::X = 4;

і знову, ви робите це у визначенні (як правило, у файлі CXX), а не в декларації (що часто є у .H файлі)


4
Якщо ви пишете бібліотеку заголовка тільки, ви можете використовувати цю техніку , щоб уникнути файл CPP: stackoverflow.com/questions/11709859 / ...
Shital Шах

62

Декларації учасників статичних даних у декларації класу не є їх визначенням. Для їх визначення слід зробити це у .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.
}

чому тут, у .CPP, це "непідписаний тест char :: X = 1;" замість "тест :: X = 1;"? статична змінна X вже визначена, навіщо ще потрібні "неподписані знаки"? @sergtk
Пенні

@Penny Тому що "тест :: X = 1;" трактується як завдання, тоді як те, що ми намагаємось зробити, - це визначення.
Анонім1847

4

Оскільки це перший потік SO, який, здавалося, з'явився для мене під час пошуку "невирішених зовнішніх сторін зі статичними членами const" взагалі, я залишу ще одну підказку для вирішення однієї проблеми з невирішеними зовнішніми тут:

Для мене те, що я забув, було позначити своє визначення класу __declspec(dllexport), і коли я дзвонив з іншого класу (за межами DLL цього класу), я, звичайно, отримав свою невирішену зовнішню помилку.
Тим не менш, легко забути, коли ви змінюєте внутрішній клас помічників на клас, доступний з іншого місця, тому якщо ви працюєте в динамічно пов'язаному проекті, ви можете також перевірити це.


2

у моєму випадку я оголосив одну статичну змінну у .h-файлі, як

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

і в myClass.cpp я намагався використовувати цей m_nMyVar. Він отримав помилку LINK на зразок:

помилка LNK2001: невирішений зовнішній символ "public: статичний клас ... Файл 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 пішов.


0

У моєму випадку я використовував неправильне посилання.
Це було керовано c ++ (cli), але з власним експортом. Я додав до linker -> input -> resource link resource DLL бібліотеки, з якої функція експортується. Але нативне посилання c ++ вимагає .lib-файлу, щоб "побачити" реалізацію в cpp правильно, тому мені допомогло додати .lib файл до linker -> input -> додаткових залежностей.
[Зазвичай керований код не використовує експорт та імпорт dll, він використовує посилання, але це було унікальною ситуацією.]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.