2

I'm having strange linkage problems with the following very simple application, which has a class inheriting both QObject and an interface class.

#include <QApplication>
#include <memory>
#include <iostream>
#include <qobject>

class IFoo {
public:
    virtual ~IFoo() {}
    virtual void foo()=0;
};

class Foo: public QObject, public IFoo
{
    Q_OBJECT
public:
    explicit Foo(QObject *parent=0): QObject(parent) { std::cout << "foo ctor" << std::endl; }
    void foo() override { std::cout << "foo::foo" << std::endl; }
};

std::unique_ptr<IFoo> createFoo() { return std::unique_ptr<IFoo>(new Foo()); }

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    auto foo = createFoo();
    return a.exec();
}

This causes the following errors:

LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl Foo::metaObject(void)const " (?metaObject@Foo@@UEBAPEBUQMetaObject@@XZ)
LNK2001: unresolved external symbol "public: virtual void * __cdecl Foo::qt_metacast(char const *)" (?qt_metacast@Foo@@UEAAPEAXPEBD@Z)
LNK2001: unresolved external symbol "public: virtual int __cdecl Foo::qt_metacall(enum QMetaObject::Call,int,void * *)" qt_metacall@Foo@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z)
LNK1120: 3 unresolved externals

I have obviously tried run qmake, clean and rebuild without effect. If I make the class Foo a plain C++ class by removing all Qt references, it works correctly.

What could be wrong?

blomm444
  • 113
  • 1
  • 8
  • If you are using a standard Qt's ".pro" file for your project, add the file you shown here to "HEADERS" variable. Without that `qmake` doesn't really run through this file and generate the required additional code. – Dmitry Sep 18 '17 at 07:42
  • 1
    Even better, move the declaration of class `Foo` to a separate header file and add that to `HEADERS` variable in the `.pro` file. – Dmitry Sep 18 '17 at 07:43
  • 1
    This is a common problem that happens when you put everything in 1 file. You have to create separate header and source files for every QObject class. That's how I always have resolved this problem. Qt deviates from standard C++ a little bit due to its MOC generator. – The Quantum Physicist Sep 18 '17 at 07:45
  • Not a dup but maybe of some help: https://stackoverflow.com/questions/1368584/what-does-the-q-object-macro-do-why-do-all-qt-objects-need-this-macro Extra file(s) are generated they need to be compiled/linked as well. – Richard Critten Sep 18 '17 at 07:53
  • The problem was indeed solved by separating everything to their own header and implementation files (as I originally had, but made this up for simplification). The problem was originally caused by the createFoo() residing in the implementation file of class Foo (foo.cpp), and moving it to its own header filed fixed the problem. Thanks. – blomm444 Sep 18 '17 at 08:17

0 Answers0