Неопределенная ссылка на виртуальную таблицу (vtable)
Когда я пытаюсь собрать свою программу на C++, я получаю сообщение об ошибке:
undefined reference to 'vtable...
В чем причина этой проблемы? Как мне это исправить?
К сожалению, я сталкиваюсь с этой ошибкой в следующем коде (класс, о котором идет речь — CGameModule), и никак не могу понять, в чем дело. Сначала я подумал, что это связано с тем, что я забыл дать реализацию виртуальной функции, но, насколько я понимаю, все здесь присутствует. Наследственная цепочка немного длинная, но вот соответствующий исходный код. Я не уверен, какую дополнительную информацию я должен предоставить.
Примечание: ошибка возникает в конструкторе, судя по всему.
Вот мой код:
cgamemodule.h
class CGameModule : public Dasher::CDasherComponent {
public:
CGameModule() : CDasherModule() {};
virtual ~CGameModule();
virtual void HandleEvent(Dasher::CEvent *pEvent);
};
cgamemodule.cpp
#include "cgamemodule.h"
void CGameModule::HandleEvent(Dasher::CEvent *pEvent) {}
Можно отметить, что CGameModule
наследуется от...
namespace Dasher {
class CEvent;
class CDasherComponent;
};
class Dasher::CDasherComponent {
public:
CDasherComponent() {};
virtual ~CDasherComponent() {};
virtual void HandleEvent(Dasher::CEvent * pEvent) {};
};
Что может быть причиной ошибки, и как я могу её устранить?
5 ответ(ов)
Для справки, забытие определения виртуального деструктора приводит к следующему сообщению об ошибке:
неопределенная ссылка на `vtable для CYourClass'.
Я добавляю это примечание, потому что сообщение об ошибке может вводить в заблуждение. (Это было в версии gcc 4.6.3.)
Я разобрался с проблемой, и она оказалась результатом плохой логики и недостатка опыта в мире automake/autotools. Я добавлял правильные файлы в мой шаблон Makefile.am, но не знал, на каком этапе нашего процесса сборки фактически создаётся сам makefile. В итоге я компилировал с устаревшим makefile, который не имел представления о моих новых файлах.
Спасибо за ответы и ссылку на FAQ по GCC. Обязательно прочитаю его, чтобы избежать возникновения подобных проблем в будущем.
Если вы используете Qt, попробуйте повторно запустить qmake. Если эта ошибка возникает в классе виджета, возможно, qmake не заметил, что таблица виртуальных функций ui класса должна быть заново сгенерирована. Это помогло решить мою проблему.
Ошибка "Undefined reference to vtable" может возникнуть в следующей ситуации. Попробуйте следующий пример:
Класс A содержит:
virtual void functionA(parameters) = 0;
virtual void functionB(parameters);
Класс B содержит:
- Определение для функции
functionA
. - Определение для функции
functionB
.
Теперь вы пишете класс C, который будете наследовать от класса A.
Если вы попробуете скомпилировать, то получите ошибку "Undefined reference to vtable for Class C".
Причина:
functionA
определена как чисто виртуальная, и её определение предоставлено в классе B.
functionB
определена как виртуальная (НО НЕ ЧИСТО ВИРТУАЛЬНАЯ), поэтому компилятор пытается найти её определение в классе A, хотя вы предоставили его в классе B.
Решение:
- Сделайте
functionB
чисто виртуальной (если это необходимо по вашей логике):
virtual void functionB(parameters) = 0;
(Это проверено и работает)
- Предоставьте определение для
functionB
в классе A, оставив его виртуальным. (Надеюсь, это сработает, хотя я это не проверял)
Вы получили эту ошибку, потому что ваш .cpp файл не был указан в makefile.
В общем, если вы забудете скомпилировать или связать определённый объектный файл, содержащий реализацию, вы столкнётесь с этой ошибкой. Убедитесь, что все необходимые файлы указаны в makefile, чтобы избежать подобных проблем.
В чём разница между g++ и gcc?
Как вывести список символов из .so файла?
/usr/bin/ld: не удается найти -l<названиеБиблиотеки>
Отладка против Релиза в CMake
Программа, скомпилированная с флагом -g в gcc, работает медленнее, чем та же программа, скомпилированная без -g?