Qt World Summit: Submit your Presentation

Use of variables in MainWindow.h

  • Under class MainWindow : public QMainWindow, I have :

    class MainWindow : public QMainWindow
    Q_OBJECT // Macro Meta Object Compiler

    QString Roger = "Roger";

    static bool isMeasureCompleted;
    static bool isCcalibrationFailed;
    static bool isMeasureWait;
    static bool isMeasureFailed ;
    static bool isDisConnect;
    // static bool bWhiteCalibFlag;

    and a few other static members. (I tried to put these flags elsewhere to no avail -- I'm open to suggestions!) But I boiled it down to the compiler rejecting ALL my variables OR rejecting ONLY one of them? You see the last flag, bWhiteCalibFlag? As it stands, it gives me this error :
    Error 1.jpg
    But if I remove the comment and Build again, all my flags become "undefined"?

    I've been at this all day...

  • static variables in class declarations are just that...declarations. they are undefined becuase you didn't define them in the cpp file.

    bool MainWindow::bWhiteCalibFlag = false;

    The difference between declaration and definition.

  • Suppose I create a brand new GUI Widget project.
    I inherit a main.cpp, a project.cpp and a project.h.
    The header is the place where I should declare my static variables, right?
    Let's stick with the same variable, static bool bWhiteCalibFlag.
    First of all, where would be the logical place to declare it?
    I drew an arrow where I believe (I'm only a beginner Qt and c++ programmer) I would logically declare it, in the public section, like this :
    Does this make any sense, so far?
    Let's say this is acceptable.
    Next, as you say, is to define it in the cpp file, right? The question is where? This is my project.cpp :
    My "intuition" tells me the variable should be defined within the constructor scope, does that make any sense? Like this :
    So far, so good?

    Now, suppose I place a pushButton in my interface, like this :
    And then, "Go to Slot" > Clicked, insert an if statement based on the status of this flag, I get "undefined reference" :

  • Lifetime Qt Champion

    Basic C++ - when you declare a static variable you also have to define it somewhere so the memory gets allocated --> https://www.cprogramming.com/declare_vs_define.html

    Apart from this - why must this variable be static?

  • I think I "understand" a little bit of what is going on...
    I removed the keyword static in the declaration of the variable, in the header file. When I built the application, the error disappeared. I was reading, last night, that, in order to use static member variables inside a function, the function itself HAS to be static also? (it took a lot of google search to figure this one out) That would explain why the error disappeared in this case.

    The whole reason I wanted to work with static variables lies in the "origin" of this new GUI Widget application I would like to develop? You see, originally, this "project idea" started as a Console application written in c++ under VS2019. It's not even 100 lines, in all? But it is being made complicated by the fact that it "interfaces" to a USB device called a "colorimeter". I was given the SDK (which I'm under NDA for) for this device by the manufacturer. The little console application I wrote successfully interfaced with the device through its various DLL calls. Could not be happier!

    In QT Creator, I first tried to re-create the same Console application I created in VS2019 but I was not successful, because the Linker could not find the DLL functions ("Unresolved External References" errors)? Which, considering my relative technical ignorance, made me abandon the project and look at C++ Builder and MFC... (there are only so many hours I can throw at this project) But later, I discovered the idea of "Explicit Linking" (to work around the darn Unresolved External References (if you can't beat them, join them!) and started experimenting with Qlibrary. It took a lot of work but I was able to write some typedef in my Qt GUI Widget project that allowed me to gain access to all the DLL functions. That was quite a milestone!

    The trouble is that there are some "flags" I need to carry with me, in this application, such as bWhiteCalibFlag, which need to be used by various functions and are not part of the DLL, they have to be my implementation?

    Not knowing Qt at all, naively, I thought about adding all these flags to the MainWindow class, so that, I thought, their values would be accessible from all member functions? But that did not work.

    Fast forward to many Aspirins later...

    There is ONE overriding particular DLL function I need to create, in my application, it is the DeviceEventHandler function, called "void EventNotice(params)". In the Console application, it sits below main() and is being called by the device as its various functions complete. It is "registered" at the beginning of the application. I guess it must be supplying the address of the EventNotice function to the DLL? In my GUI Widget application, I tried to locate the declaration / definition of the EventNotive function at different places in the code, and the only place it "worked" was inside the MainWindow class, as a public member function. Since this function only needs to exist "once" in memory, I made it static. (I don't dare post pages and pages of code?)

    I got to a point, last night, where I was able to fire a button in the interface, and in the slot code, I was able to Load the DLL (Qlibrary), resolved the functions addresses using typefefs and successfully call the EventNotice function.

    But that's when troubles started...

    Why? Because I could not situate the "LoadDLL" call independently of any buttons? I could not situate the typedefs that access the DLL functions independently of any buttons and yet they have to be accessible from anywhere in my code, any buttons? I need buttons to Initialize the device, to Calibrate the device and to Take measurements through the device, and each of these functions need access to the DLL functions.

    I tried to create a 'Device' class from where I would access the device, but I did not get very far because it was not working...

    I went to bed at 2 am, trying to solve the problem but I'm really not an expert in c++ or OOP, as you can see. I was looking through the Examples and thought, perhaps, that my application resembled the 'Camera Example' since it's got 'Initialization' and other similar functions like 'Take a picture' and so on? I stumbled upon this QscopePointer notion that is used in the 'Camera Example', which, intuitively, tells me may help? Which, possibly, as far as I could see in the Example code, would provide some sort of "central location" for the device, to allow accessing it from anywhere in the code?

    Please excuse my newbie questions... but it's not easy to find examples from which to build my application... YouTube and the Qt site are full of "basic" GUI Widget examples but nothing which explains the "approach" I need to take in my case....

    I thought about going back to my Console application and stick with menu commands but that would be "throwing the towel" :(

  • Lifetime Qt Champion

    @RogerBreton said in Use of variables in MainWindow.h:

    the function itself HAS to be static also? (it took a lot of google search to figure this one out) That would explain why the error disappeared in this case.

    This is completely wrong and I already explained why the error occurs. I would suggest a good c++ book first before starting with Qt.

  • I would have hope you could have offered some suggestions or ask simple fragen zum meine humble projekt, to help, instead of openly criticize me and send me back to read programming books. Know that alles der gut c++ programming books I have had the chance to read nicht cover "Qt" und never cover device interface oder DLL loading mit resolve function names mit typedefs... I have spent a great deal of time BEFORE coming back for more help here.

  • @RogerBreton Don't worry, I will tell you what to do.
    If you still want to use static variables in your class like in your initial post, this is the way to do it.

    //THIS GOES IN YOUR .H file
    class SomeClassName
    //Making it public, private, protected does not matter. These are just language side concepts.
    static int variable;
    static int SuperArray[1000];
    void function();
    static void function2(); <--------notice the word static
    //Put this after your #include directives.
    int SomeClassName::variable=0;
    int SomeClassName::SuperArray[1000];

    You can use those variables in function() and function2().
    Be careful when making multiple instances of SomeClassName. There would be only one copy of variable and SuperArray that all your instances will share.

    Anything else?

  • @stretchthebits Thank you for your suggestions :-)
    I feel I'm making progress.

    In mainwindow.h, I added :

    class SomeClassName
    static int variable;
    static int SuperArray[1000];
    static bool isMeasureCompleted;
    static bool isCcalibrationCompleted;
    static bool isCcalibrationFailed;
    static bool isMeasureWait;
    static bool isMeasureFailed;
    static bool isDisConnect;
    static uint32_km portCount; <-- mfr typedef
    static uint8_km StateTable[2][4]; <-- mfr typedef
    static char input_buf[64]; <-- mfr typedef
    static uint8_km dev_no; <-- mfr typedef
    static DDD_PortInfo portInfo[16]; <-- mfr typedef
    static bool bExitFlag;
    static bool bSelectExitFlag;
    static bool bWhiteCalibEndFlag;
    static bool bIrradianceCalibEndFlag;
    static bool bRadianceCalibEndFlag;
    static void EventNotice(DDD_eEventCode outEventCode, uint32_km outRAWDataCount, DD_ERROR_TYPES outError); <-- mfr DeviceEventHandler
    static void Initialize();

    Then, in mainwindow.cpp, I added this :

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    int SomeClassName::variable=0;
    int SomeClassName::SuperArray[1000];
    bool SomeClassName::isMeasureCompleted=false;
    bool SomeClassName::isCcalibrationCompleted=false;
    bool SomeClassName::isCcalibrationFailed=false;
    bool SomeClassName::isMeasureWait=false;
    bool SomeClassName::isMeasureFailed=false;
    bool SomeClassName::isDisConnect=false;
    bool SomeClassName::bExitFlag=true;
    bool SomeClassName::bSelectExitFlag=true;
    bool SomeClassName::bWhiteCalibEndFlag=false;
    bool SomeClassName::bIrradianceCalibEndFlag=false;
    bool SomeClassName::bRadianceCalibEndFlag=false;
    uint32_km portCount;
    char input_buf[64];
    uint8_km dev_no;
    DDD_PortInfo portInfo[16];
    uint8_km StateTable[2][4] = { "Eth", "USB" };

    When I build the project, I get this "weird" error :
    The variable is declared in the .H file and defined in the .CPP file, yet, the compiler does not "recognize" it:

    Yesterday night, at 2 am, as soon as I deleted this variable, ALL HELL BROKE LOOSE. So I don't dare deleting it yet.....

  • Things are slowly sinking in... Experimenting with the above error message...
    This code is executing inside a "member function" :
    Project 12.png
    Incidently, I was listening to someone explaining that static variables did NOT need to be instantiated? Slowly... So, I experimented with the SuperArray variable and could was able to conclude that they couldn't be use inside my member function... This is going to be interesting, in terms of "conceptual understanding" -- thank you all for your patience and help.

  • It took me a while but I didn't think it was a "lost cause". I tried first creating a "function" that would allow me to access the variable from outside the member function? I would pass this function the variable and in the body of that function, I would merely assign the value to the 'private" variable. But the compiler did not let me play that game? ... Then I "reasoned" that's what 'getters' and 'setters' are for? But then, looking at some example on the internet, it dawn on me that my SomeClass declaration did not have any 'scope qualifier' (I'm not sure that's how they're called, technically?) but it dawn on me, at that point that, what about adding a public: keyword before the declaration of all those flags? That sounded almost too easy to be true? This is what I did :
    Project 13.jpg
    See? And then, tadam!, the error disappeared :
    Project 14.png
    Next step is to try to build and run this "monster" :-)

  • @RogerBreton
    In C++ class declarations if you do not write any of the public:, protected:, private: access specifiers the following variables/methods default to private. It is good practice to always type the desired specifier from the start.

    It is good now that you have understood what is required if you declare a member variable as static. (static is a bit different in C++ if you are used to it for C.)

    I don't claim to have read/followed all that you have written about why you are using static above. But my natural inclination is surprise that you want to use it. There are times, but not that often, and there has to be a particular reason. In the case of your SomeClass, for example, code can create many separate instances of that class (SomeClassName instance or SomeClassName *instance = new SomeClassName). But your code means that there will only be one single instance of variable, SuperArray & isMeasureCompleted shared across all those instances. They won't have their own copies of these. Why do you want that?

  • Lifetime Qt Champion

    @RogerBreton said in Use of variables in MainWindow.h:

    instead of openly criticize me and send me back to read programming books.

    Yes, because you lack basic c++ stuff. Sorry but your question and the strange unneeded use of static functions are c++ basic stuff (and don't even have something to do with Qt). Learn c++ first before starting with Qt since Qt is a c++ library and without basic knowledge it's impossible to use Qt properly.

  • @RogerBreton Getters and setters are a thing that C++ books recommend. Personally, I don’t strictly follow that rule because it turns the code very verbose. It’s up to you but OOP people will hate you.
    Sometimes, I just want to read a variable from one class and give it to another. For example:

    SomeClass1 a;
    CubeClass b;

    Anyway, that’s up to you.
    In C++, by default, like JonB said, your member functions and member variable are private.
    Sounds like you want to declare them as public.
    For structs, by default, they are public.

    I think what you want to do is to declare an instance of SomeClassName in your MainWindow class.
    And then, the code becomes
    SomeClassName TheObject;

    if (SUCCESSFUL(sdkError)) {
         TheObject.bWhiteCalibEndFlag = true;

Log in to reply