Avatar ·

Ошибка "undefined reference/unresolved external symbol" в C++: причины и исправление

Всем привет! Я новичок в C++ и уже несколько часов бьюсь над ошибкой, которую не могу понять. Компилятор выдает что-то вроде: ``` undefined reference to `MyClass::myFunction()' ``` или ``` unresolved external symbol "public: void __thiscall MyClass::myFunction(void)" (?myFunction@MyClass@@QAEXXZ) referenced in function _main ``` Вот мой код. У меня есть три файла: **main.cpp:** ```cpp #include "myclass.h" int main() { MyClass obj; obj.myFunction(); return 0; } ``` **myclass.h:** ```cpp #ifndef MYCLASS_H #define MYCLASS_H class MyClass { public: void myFunction(); }; #endif ``` **myclass.cpp:** ```cpp #include "myclass.h" #include void MyClass::myFunction() { std::cout << "Hello from myFunction!" << std::endl; } ``` Я компилирую в Visual Studio или через g++ одной командой: `g++ main.cpp -o program`. Всё падает с этой ошибкой. Я проверил, что файлы в одной папке, заголовочный файл подключен правильно, имя функции совпадает. В чём может быть дело? Как это исправить? Объясните, пожалуйста, что такое undefined reference и почему он возникает. Заранее спасибо! <<>>

Что такое undefined reference / unresolved external symbol?

Эта ошибка возникает на этапе компоновки (линковки), когда компилятор уже успешно обработал все исходные файлы, но линковщик (linker) не может найти реализацию (тело) функции или переменной, которая была объявлена (например, в заголовочном файле) или использована. В вашем случае: в main.cpp вызывается MyClass::myFunction(), но линковщик не видит её определения из myclass.cpp.

Почему это происходит в вашем коде?

Вы компилируете только main.cpp: g++ main.cpp -o program. Файл myclass.cpp не участвует в компиляции. Компилятор обрабатывает main.cpp, видит объявление класса в myclass.h и генерирует вызов myFunction, но не знает, где её код. Линковщик затем ищет этот код во всех объектных файлах, но находит только main.o — и выдаёт ошибку.

Как это исправить?

Нужно скомпилировать и связать оба файла вместе. Есть несколько способов:

1. Компиляция всех .cpp файлов в одной команде

g++ main.cpp myclass.cpp -o program

Или для Visual Studio (из командной строки разработчика):

cl main.cpp myclass.cpp

2. Раздельная компиляция (рекомендуется для больших проектов)

g++ -c main.cpp -o main.o
g++ -c myclass.cpp -o myclass.o
g++ main.o myclass.o -o program

Флаг -c означает «только компиляция, без линковки». Затем вы линкуете объектные файлы.

3. Использование make-файла или CMake

Для автоматизации процесса создайте Makefile:

program: main.o myclass.o
	g++ main.o myclass.o -o program

main.o: main.cpp myclass.h
	g++ -c main.cpp -o main.o

myclass.o: myclass.cpp myclass.h
	g++ -c myclass.cpp -o myclass.o

Или используйте CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyProject)
add_executable(program main.cpp myclass.cpp)

Другие частые причины undefined reference:

  • Забыли #include заголовочный файл — но не ваш случай.
  • Не подключили библиотеку (например, -lm для математических функций, -lpthread для потоков).
  • Опечатка в имени функции в объявлении или определении (например, myfunction vs myFunction).
  • Определение функции в .cpp, но не объявлено в .h — линковщик не найдёт, если вызывать из другого файла.
  • Статические или inline функции — если функция объявлена как static в заголовочном файле, она не будет видна в других единицах трансляции.
  • Функции-члены класса, объявленные, но не определённые — проверьте, что все методы имеют реализацию.

Как отлаживать?

Используйте флаги для линковщика: g++ -v main.cpp myclass.cpp -o program покажет, какие файлы ищутся. В Visual Studio включите подробный вывод линковки (Project Properties → Linker → General → Show Progress).

Ваш код корректен, проблема только в том, что вы не передали myclass.cpp компилятору. Добавьте его в команду — и всё заработает!

<<>>

Альтернативный подход: проверьте настройки IDE и порядок компиляции

Если вы используете IDE (Visual Studio, Code::Blocks, CLion), ошибка может возникать, если файл myclass.cpp не добавлен в проект. В Visual Studio: щёлкните правой кнопкой по проекту → Add → Existing Item → выберите myclass.cpp. В Code::Blocks: в панели проектов добавьте файл через Add files.

Также проверьте порядок файлов при линковке. В некоторых старых компиляторах (например, MinGW) порядок имеет значение: библиотеки должны идти после объектных файлов, которые их используют. Для вашего случая команда g++ main.cpp myclass.cpp всегда корректна, но если вы добавляете библиотеки, ставьте их в конец:

g++ main.o myclass.o -lpthread -o program

Дополнительная причина: забыли extern "C"

Если вы смешиваете C и C++ код, функция, объявленная в C-стиле, должна быть обёрнута в extern "C":

// myclass.h
#ifdef __cplusplus
extern "C" {
#endif
void c_function();
#ifdef __cplusplus
}
#endif

Иначе линковщик будет искать искажённое (mangled) имя C++, а найдёт C-имя — и выдаст unresolved external.

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