Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

scope of variables in slots



  • I've got the following code. In my slot, it says xml is undefined in dataReadyToRead. I've tried everything I can think of including prefixing it with this-> and it says no member xml in MainWindow even though it clearly is!

    This is just a rough draft to get everything working correctly

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "podcastitem.h"
    #include "ui_podcastitem.h"
    #include <QDebug>
    #include <QXmlStreamReader>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        netManager = new QNetworkAccessManager(this);
        netReply = nullptr;
        mDataBuffer = new QByteArray();
        QXmlStreamReader xml;
    
        //Define Network Request
        QNetworkRequest request;
        request.setUrl(QUrl("https://destinationlinux.org/feed/mp3"));
    
        netReply = netManager->get(request);
        connect(netReply, SIGNAL(readyRead()), this, SLOT(dataReadyToRead()));
        connect(netReply, SIGNAL(finished()), this, SLOT(dataReadFinished()));
    
        QString title = "Some new text";
        QPixmap image = QPixmap("C:/Users/tausciam/Desktop/Programming/RoSeS/resources/dl191-mp3-cover.jpg");
        PodCastItem *podcastItem = new PodCastItem(this,title,image);
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::dataReadyToRead()
    {
        mDataBuffer->append(netReply->readAll());
        this->xml->addData(mDataBuffer);
        parseXML();
    }
    
    void MainWindow::dataReadFinished()
    {
        if(netReply->error()){
            qDebug() << "Error: " << netReply->errorString();
        }else{
            qDebug() << QString(*mDataBuffer);
        }
    }
    
    void MainWindow::parseXML()
    {
    
    }
    


  • Do you understand the purpose of a class definition vs implementation? The way you've defined xml it only exists in the constructor. this-> does nothing if the target hasn't been defined in the class deifnition.



  • @Kent-Dorfman Probably not. I did try it like the others above. If I call it like

    QXmlStreamReader *xml = new QXmlStreamReader;

    it doesn't throw any errors, but I still can't use it in my slot. It still says undefined. If I don't make it a pointer, I get errors



  • Your problem is basic C++. If you define QXmlStreamReader xml; in the constructor then it exists nowhere except in the constructor, unless you've defined it in the class definition.



  • @tannhaus
    What @Kent-Dorfman is telling you is: as long as you have QXmlStreamReader xml; inside MainWindow::MainWindow() that variable disappears at the end of that method, and you cannot access the xml variable in any other method. If you want it to persist and be accessible to other methods after the constructor has concluded, you must move it to being a member variable of MainWindow.


  • Moderators

    @tannhaus The basic premise of variable scope in C++ is that the } is the killer of variables.

    void SomeClass::foo()
    {
        if (something)
        {
           int variable = 42;
           // ok to use variable here
        }
        // doesn't exist here
    }
    
    //doesn't exist here either
    
    void SomeClass:: bar()
    {
        // certainly doesn't exist here
    }
    

    Put your variable in the class declaration:

    class SomeClass
    {
       int variable;
    }; 
    

    For classes you can think of their } as the same as their destructor's }, so you can use it in any method of that class:

    class SomeClass
    {
       int variable;
    
       void foo() { // variable is still here  }
       void bar() { // here too  }
    }; 
    
    // but not here
    
    void someRandomFunc()
    {
       // and not here
    }
    


  • @JonB Thanks. I thought it was a member variable because I declared it inside of MainWindow, but apparently declaring it in the header instead then using a pointer to mDataBuffer does make it compile without errors.



  • @Chris-Kawa Thank you. It's a stupid beginner mistake, but I thought calling a function from mainwindow that is prefixed with MainWindow:: would give it the scope of mainwindow. But, apparently only if you declare it in the header. I can't believe I spent a couple of hours on that and that was the reason, but there it is.


  • Moderators

    @tannhaus Yeah, all class members need to be in the class declaration. This is because the compiler needs to know the size of the class just by reading its declaration. Basically when you include the header the sizeof(YourClass) needs to be calculable.

    Imagine if you could declare a class member anywhere in its methods. It would be impossible to determine the size of the class. What if the function was never called. Does the variable inside still count to the size of the class? What if you declared a variable in a if statement? Sometimes counts and sometimes not?

    C++ is statically typed and all types have a constant size calculated at compile time from their type declaration.


Log in to reply