Попробую описать ситуации, когда может возникнуть данная ошибка, и дать несколько советов, как избежать её.
Чаще всего данное сообщение всплывает, если вы используете MOC.
MOC (Meta-Object Compiler, переводится как Метаобъектная система/компилятор) – механизм, который расширяет синтаксис C++.
MOC:
- необходим для механизма сигналов-слотов;
- позволяет программисту получать метаинформацию о подклассах QObject (QObject::metaObject());
- используется для интернационализации приложений (QObject::tr());
- содержит в себе полезные расширения синтаксиса C++.
При появлении ошибки «undefined reference to vtable», первым делом очистите проект и пересоберите его, не забыв запустить qmake:
make clean
# удалите вручную все moc-файлы, если они остались после выполнения make clean
rm Makefile
qmake
make
Если ошибка не исчезла, то проверьте файл проекта (*.pro). Проверьте, чтобы все необходимые заголовочные файлы (включающие сигналы и слоты особенно) были включены в проект. Список заголовочных файлов должен содержаться в переменной HEADERS:
HEADERS += firstHeaderFile.h \
otherHeaderFile.h \
secondHeaderFile.h
Если вы используете в проекте папку, содержащую заголовочные файлы, убедитесь, что добавили эту папку в переменную INCLUDEPATH:
INCLUDEPATH += ./include
Если обнаружили забытый h-, hpp-файл – пересоберите проект заново.
Проблема осталась? Тогда ещё варианты:
- Загляните в c-, cpp-файлы и убедитесь, что классы там не определяются. MOC разбирает только заголовочные файлы;
- Каждый класс, который имеет сигналы или слоты должен наследоваться от QObject, напрямую или нет.
В начале определения таких классов обязательно должнен стоять макрос Q_OBJECT, к примеру:class MyWidget : public QWidget
{
Q_OBJECT
/* класс наследуется от QWidget, а значит и от QObject,
* следовательно должен содержать макрос Q_OBJECT.
* Если класс наследуется от QObject, но не содержит сигналов или слотов,
* то не обязательно включать макрос в описание класса.
*/
...
} - Ещё одна вещь, которую можно проверить.
Удалите Makefile и посмотрите, что выдаст qmake в Makefile:
rm Makefile
qmake
Откройте Makefile редактором и найдите следующие строки:
и
compiler_moc_header_make_all:
compiler_moc_header_clean:
Например, в моем Makefile есть:mocclean: compiler_moc_header_clean compiler_moc_source_clean
mocables: compiler_moc_header_make_all compiler_moc_source_make_all
compiler_moc_header_make_all:
release/moc_mainwindow.cpp release/moc_SystemConfiguration.cpp release/moc_InstrumentConfiguration.cpp release/moc_ModuleConfiguration.cpp release/moc_ChannelConfiguration.cpp
compiler_moc_header_clean:
-$(DEL_FILE) release\moc_mainwindow.cpp release\moc_SystemConfiguration.cpp release\moc_InstrumentConfiguration.cpp release\moc_ModuleConfiguration.cpp release\moc_ChannelConfiguration.cpp
Каждый заголовочный файл, содержащийся в проекте и
нуждающийся в обработке MOC-компилятора, должен находиться в этих строках.
Имя файла будет начинаться с прифекса «moc_».
Проверьте, что в список включены все h-файлы (точнее, только те, которые требуют обработку MOC-компилятором).
Если Вы не обнаружили какой-либо moc-файл, не спешите править руками Makefile,
просто подправьте pro-файл нужным образом.
Если файл проекта правилен, то qmake генерирует правильный Makefile.
Хорошая статья
ОтветитьУдалитьОгромное спасибо! Мне даже в голову бы не пришло
ОтветитьУдалить>Загляните в c-, cpp-файлы и убедитесь, что классы там не определяются. MOC разбирает только заголовочные файлы;
Потому что сейчас писал простенькое приложение, только разбираюсь в языке, поэтому простейший класс и объявлял в основном файле. А тут вон оно как)
Спасибо!
Спасибо большое!
ОтветитьУдалить>Загляните в c-, cpp-файлы и убедитесь, что классы там не определяются. MOC разбирает только заголовочные файлы;
Тоже ломала голову, почему все заработало, когда перенесла объявление класса в hник.
Если же все-таки класс определен в CPP, например, в main.cpp, и нет желания делать для него отдельные h/cpp файлы, можно включить его moc-файл явно, вот так:
ОтветитьУдалить---
[main.cpp]
#include
#include
class MyObject : public QObject
{
Q_OBJECT
};
int main( int argc, char** argv )
{
QApplication app( argc, argv );
MyObject ob;
return app.exec();
}
#include "main.moc"
Большое спасибо! Не знал насчет заголовочных файлов!
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалить