Search code examples
c++qtqtcoreqtnetworkmoc

Undefined reference to in Constructor with QNetworkAccessManager derived class


I am trying to read a html page using the following code which uses Qt libraries

 #include <QtWidgets/QApplication>
    #include <QtNetwork/QNetworkRequest>
    #include <QtNetwork/QNetworkReply>
    #include <QtNetwork/QNetworkAccessManager>
    #include <QtCore/QString>
    #include <iostream>

    class SillyRequest : public QNetworkAccessManager

{
    Q_OBJECT
    public:
        SillyRequest();
        QString getData();
    public slots:
        void replyFinished(QNetworkReply *);
    private:
       QString collectedData;
};
QString SillyRequest :: getData()
{
    return collectedData;
}
SillyRequest :: SillyRequest()
{
    connect(this, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}

void SillyRequest :: replyFinished(QNetworkReply *reply) 
{
    collectedData = reply->readAll();
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    SillyRequest *network = new SillyRequest;

    QNetworkRequest request;

    request.setUrl(QUrl("http://qt.nokia.com"));

    request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");

    QNetworkReply *reply = network->get(request);

    std :: cout << network->getData().toStdString() << std :: endl;

    return app.exec();

}

I get the following error when I compile. Am not sure what I am not doing in the right way.

testing.cpp:(.text+0x73): undefined reference to `vtable for SillyRequest'
collect2: error: ld returned 1 exit status
Makefile:192: recipe for target 'network' failed
make: *** [network] Error 1

I have inherited from QNetworkAccessManager so as to implement the 'replyFinished' slot. Signal 'finished' is already part of the 'QNetworkAccessManager'.


Solution

  • There are so many issues with your short code, but I will focus below on the most central part of those.

    Include the moc file

    The general practice is this:

    void SillyRequest :: replyFinished(QNetworkReply *reply) 
    {
        collectedData = reply->readAll();
    }
    
    #include "main.moc" // This is the addition
    
    int main(int argc, char **argv)
    

    The problem is that your class is not in separate header and source files and so qmake and hence moc are in no position to be aware of this.

    As a side note, you could also inline all the methods in this special case.

    Separate header and source

    If you do not want to explicitly include the moc (meta object compiler) file generated on the fly, you would need to establish a separate header (and preferably source) for your own class and then you can include the header in your main.cpp file. You would then do this in the beginning of the main.cpp:

    #include "sillyrequest.h"
    

    and naturally, you would extend the qmake project file as follows:

    HEADERS = sillyrequest.h
    SOURCES = sillyrequest.cpp main.cpp