Unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Parent

I inherited a class from QObject:

class Parent: public QObject
{
    Q_OBJECT
    QObject* cl;

public:
    Parent(QObject *parent=0):QObject(parent) {
        cl = NULL;
    }

    QObject* getCl() const {
        return cl;
    }
    void setCl(QObject *obj) {
        cl = obj;
    }
};

But when I write:

Parent ev;

Я получаю следующую ошибку:

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Parent::metaObject(void)const " (?metaObject@Parent@@UBEPBUQMetaObject@@XZ)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void * __thiscall Parent::qt_metacast(char const *)" (?qt_metacast@Parent@@UAEPAXPBD@Z)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual int __thiscall Parent::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Parent@@UAEHW4Call@QMetaObject@@HPAPAX@Z)

28 ответов

Решение

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

Если вы используете Visual Studio, удалите строку Q_OBJECT из заголовочного файла, сохраните файл, положите Q_OBJECT обратно в заголовочный файл, сохраните файл еще раз. Это должно генерировать moc_* файл и должен построить и связать правильно.

Я заметил, что некоторые ответы основаны на Visual Studio.

Этот ответ основан на Qt Creator.

В отличие от названия предполагают, Rebuild Project не будет все уничтожать и строить с нуля. Если вы недавно добавили QObject (и / или Q_OBJECT) для вашего класса, вам придется запустить qmake опять, например

  1. Чистый Проект
  2. Запустите qmake
  3. Построить проект

Это потому, что по умолчанию qmake запускается только тогда, когда вы вносите значительные изменения в свое решение, например добавляете новые исходные файлы или изменяете .pro файл. Если вы вносите изменения в существующий файл, он не знает, что нужно запустить qmake,

В качестве отступления, чтобы заставить Qt собрать все с нуля, удалите Debug или же Release папка.

Поэтому проблема была в том, что мне нужен компилятор Qt MOC для компиляции моего файла.h. Это необходимо для любых классов, расширяющих QObject или одного из его дочерних классов. Исправление вызвало (для меня) щелчок правой кнопкой мыши по файлу заголовка, выбрав "Свойства" и установив "Тип элемента" на "Qt MOC Input", затем нажав "Компилировать" в заголовке, а затем добавив полученный файл moc_myfilename.cpp в мой файл. проект.

Я добавил файлы cpp/ui в свой проект вручную, но забыл явно добавить файл заголовка в качестве файла заголовка. Теперь при компиляции я получил сообщение об ошибке, подобное приведенному выше, и файлы moc_*. Cpp не были сгенерированы в каталоге отладки (или выпуска) сборки. Это не было такой очевидной ошибкой, qmake не жаловался, и кроме сообщения компоновщика, я не получил никаких ошибок.

Поэтому, если кто-то снова сталкивается с той же проблемой (или совершает ту же ошибку копирования и переноса): убедитесь, что файлы заголовков также были добавлены в файл проекта.

Если ваши файлы moc сгенерированы в проекте Visual Studio, попробуйте включить их в проект, если они не включены в проект, а затем пересоберите.

У меня была та же проблема в Visual Studio, и я решил ее, выполнив следующие шаги:

  1. Щелкните правой кнопкой мыши заголовочный файл в обозревателе решений.
  2. свойства
  3. Измените "Тип элемента" на "Custom Build Tool"

Затем в конфигурации Custom Build Tool:

  1. Перейти к генералу
  2. установите "Командную строку" на:

    "$ (QTDIR) \ bin \ moc.exe" "% (FullPath)" -o ". \ GeneratedFiles \ $ (ConfigurationName) \ moc _%(имя файла).cpp" "-fStdAfx.h" "-f../../../src/FileName.h"-DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_NETWORK_LIB -DWIN32_LEAN_AND_MEAN -DDIS_VERSION = 7 -D_MATH_DEFINES_DEFINED "-I. \ SFML_STATIC"" -I. \ GeneratedFiles "" -I. " "-I $ (QTDIR) \ include" "-I. \ GeneratedFiles \ $ (ConfigurationName)." "-I $ (QTDIR) \ include \ QtCore" "-I $ (QTDIR) \ include \ QtGui" "-I $ (QTDIR) \ include \ QtNetwork"

  3. установите "Выходы" на:

    . \ GeneratedFiles \ $ (ConfigurationName) \ MOC _%(Имя файла).cpp

  4. установите "Дополнительные зависимости" на:
    $ (QTDIR) \ Bin\moc.exe;%(FullPath)


Ваши точные значения могут отличаться. Они обычно применяются через плагин Qt.

У меня была эта проблема с Visual Studio 2012, когда в моем файле cpp было определение класса Q_OBJECT. Перемещение определения класса в заголовочный файл решило проблему.

Похоже, что должна быть возможность поддерживать класс Q_OBJECT в файле cpp, добавив файл cpp в moc, но я не пробовал этого.

Я использую CMake для управления проектами Qt, и новый вызов Q_OBJECT необходимо добавить в вызов QT4_WRAP_CPP. Это сгенерирует moc_*. Cxx для включения в проект и очистит неразрешенные внешние компоненты.

Столкнулся с этой проблемой в случае связанных целей CMake. Оказалось, мне пришлось включить CMAKE_AUTOMOCдаже в целях, которые не использовали Qt напрямую (транзитивно). Также оказалось, что CMAKE_AUTOMOC нельзя использовать без find_package(QtX) в том же CMakeLists.txt или же CMakeLists.txt родителя.

Моя проблема заключалась в том, что один из моих файлов, в которых использовался макрос Qt, не был перемещен. Я обнаружил, что плагин Qt для Visual Studio не распознает Q_NAMESPACE макрос и, следовательно, не добавляет файл в список moc'ing.

Поэтому я использовал решение из этого ответа, чтобы добавить файл в список микрофонов:

Вы должны найти файл.h, который успешно сгенерировал "moc_*", и скопировать все содержимое в "Custom Build Tool -> General" на новую страницу настроек файла.h.

Будьте осторожны с различными вариантами Debug а также Release-Режим.

После этого постройте свой проект.

Построить его один раз каждый в Debug а также Release-Режим

Наконец, добавьте сгенерированный файл "moc_ *" в ваш проект.

Теперь "moc_filename.cpp" должно быть в Generated Files\Debug а также Generated Files\Release,

Щелкните правой кнопкой мыши по каждому из них и измените их свойства:

  • Файл в Debug: Изменить конфигурацию на Release а затем изменить General->Excluded from build в yes,
  • Файл в Release: Изменить конфигурацию на Debug а затем изменить General->Excluded from build в yes,

Используя QtAdd-in с VS2010, я понял, что файлы moc_*. Cpp были обновлены в папке GeneratedFiles/Debug, хотя я находился в режиме выпуска. Копирование файлов в папку Release работало для меня.

Я знаю, что это очень старый вопрос, но он, кажется, все еще интересен (я был здесь по крайней мере 4 или 5 раз за последние месяцы) и, кажется, я нашел другую причину, по которой возможно получить эту ошибку.

В моем случае в заголовочном файле я неправильно набрал:

#include "MyClass.h""

Только после проверки всего вывода я обнаружил, что в этой строке компилятор выдает предупреждение.

Теперь, когда я удалил дополнительную кавычку, мой QObject отлично компилируется!

Для Visual Studio 2022 (с расширением Qt VS Tools)

В обозревателе решений щелкните правой кнопкой мыши соответствующий файл заголовка и выберите «Свойства».
В разделе «Свойства конфигурации -> Общие -> Тип элемента» выберите параметр «Компилятор метаобъектов Qt (moc)». Затем перестройте проект.

В моем случае (с использованием QtAdd-in с VS2012 и Qt v4.8.4) ни одно из приведенных выше предложений не сработало. По какой-то причине VS не смог сгенерировать правильные файлы moc (выходные данные сборки: соответствующие классы не найдены. Выходные данные не созданы.) И когда я скомпилировал соответствующие заголовки вручную (установив qt moc в качестве компилятора и нажав "Compile"), он создал пустой файл moc,

Что сработало, так это скомпилировали все необходимые mocs из командной строки (moc -o moc_SomeClass.cpp SomeClass.h), а затем заменили неправильные в папке GeneratedFiles.

Это только обходной путь (и не удобный для большого проекта) для успешной сборки вашего проекта, но на самом деле он не объясняет странного поведения VS/QtAdd-in.

Visual Studio 2017.

Я добавил файл в уже настроенный проект Qt и получил эту ошибку. Как я это исправил:

Щелкните правой кнопкой мыши заголовок в Свойствах обозревателя решений ... -> Свойства конфигурации -> Общие -> Изменение типа элемента с заголовка C/C++ на компилятор метаобъектов Qt (moc)

вуаля:)

Я столкнулся с этой проблемой при использовании "частного класса" в Qt при использовании шаблона программирования " PIMPL " (частная реализация). Qt использует эту модель на всем протяжении их исходного кода. Мне самому это очень понравилось.

Этот метод предполагает использование "частного" заранее объявленного класса в общедоступном заголовочном файле, который будет использоваться "открытым" классом (т. Е. Его "родительским"). Затем родительский объект имеет указатель на экземпляр закрытого класса в качестве члена данных.

"Закрытый" класс полностью определен в файле cpp для общедоступного. НЕТ заголовочного файла для частного класса.

Вся "грязная работа" делается с этим частным классом. Это скрывает всю реализацию вашего общедоступного класса, включая каждого другого частного члена, как правило (как данные, так и функции).

Я настоятельно рекомендую узнать о шаблоне PIMPL - особенно если вы собираетесь когда-либо читать внутренний источник Qt.

Без объяснения этого стиля кодирования, вот в чем смысл этого вопроса... Чтобы получить Q_OBJECT макрос для работы внутри cpp для того, чтобы "private" класс был QObject, который может использовать сигналы / слот и т. д., вам нужно было явно включить.moc в открытый класс внутри cpp:

#include "MyPublicClass.moc"

Вы можете игнорировать любые предупреждения IDE об этой строке.

Я не уверен, что это действительно имеет значение, но это включение я всегда вижу ПОСЛЕ определения частного класса, а не в верхней части cpp (как обычно включаются включения). Итак, компоновка cpp выглядит так:

  1. "Нормальные" включения определены.
  2. Закрытый класс определен.
  3. МОК для общественного класса #included.
  4. Реализация открытого класса определена.

В моем случае у меня были файлы .h и .cpp для проблемного предка QObject в подпапках проекта. Когда я переместил их рядом с CMakeLists.txt (корневая папка проекта), он успешно связался. Вероятно, мне не хватает какой-то команды CMake для включения файлов mocs fot в подкаталоги.

когда я удалил Q_OBJECT, он отлично работает.

Я использую Clion + CMake + MSVC/14.31.31103.

Это потому, что Q_OBJECT больше не нужен после этого?

      set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

В Qt Creator

Оказалось, что у меня была эта ошибка, потому что я потом добавил Q_OBJECT в файл .h.

Мне удалось исправить это после удаления и добавления файла обратно в проект.

Удачного кодирования...

Это случилось со мной недавно при переходе с MingW на MSVC. У меня был прототипный класс / структура, перечисленные как класс, и MingW не возражал.

MSVC определенно видит разницу между class а также struct когда прототипирование касается.

Надеюсь, что это поможет кому-то еще однажды.

В моем случае ничего из вышеперечисленного не сработало, но это была моя ошибка.

Я переопределил виртуальные функции в файле.h (объявил их), но никогда не определял их в.cpp:)

Любой ответ работает для меня в среде VS 2013. В конце концов, я решил проблему, удалив файл.h /.cpp из проекта и добавив его обратно.

Я работаю в VisualStudio только с проектом C++, который имеет QT-интерфейс. Простое удаление строки Q_OBJECT позволяет избежать ошибок компоновщика. Кажется, не оказывает никакого неблагоприятного воздействия.

У меня та же проблема, мое решение заключалось в кодировке (мой файл с "UTF16LE BOM" не может быть сгенерирован с помощью moc.exe), вы создаете другой файл с ASCII, и он работает.

HxD HexEditor может помочь вам увидеть кодификацию.

Для меня это причина: какой-то заголовочный файл или исходный файл не включены в файл проекта QT

Я работаю в VS2015 с интегрированным клиентом Perforce p4v. В моем случае Perforce попытался добавить moc-файл в депо, когда я отменил эту операцию, Perforce удалил этот moc-файл из проекта и удалил его. Файл был воссоздан после следующей компиляции, но он не был включен в проект, я должен был добавить его вручную в Сгенерированные файлы, когда я наконец понял, в чем проблема.

Я решил свою проблему, добавив это в мой заголовочный файл:

#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H

... // all the header file content.

#endif
Другие вопросы по тегам