Introduction to Qt / QML (Part 43) - Signals and Slots Errors

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hi. You're watching Programming with Qt and QML. We're down in the machine room at the C++   level. In this video, which is likely going to be  very short, I'm going to show you what you will   experience if you forget the Q_OBJECTS. And then  I'll explain to you what is really going on there.   The code that we had in just the example before  looks like this. It's the StopWatch that just   counts up the numbers here. The way that it  works, let's just go to our main,   just create an instance of our StopWatch.  The StopWatch is this Q_OBJECT  macro. Here's a subclass from QObject. So, it has  this Q_OBJECT macro. It has one slot,   and whenever this slot is being  connected to from this timer in my constructor.   Okay. Let's imagine that I forgot this Q_OBJECT macro here. Let's see what it says   when I compile it. So first of all, it's perfectly  okay to forget this Q_OBJECT macro   here because, well it's not. It says Q_OBJECT...."Class declaration lacks Q_OBJECT macro."   And why is that? Well, it is because  QMake's actually been executed and the make system thinks  that it should be doing this. So let me just   run QMake again...Builds...Run QMake...and compile again.  And this time, it doesn't complain. It just compiles   fine and everything's cool. Now, let's try the  other way around. Let's try that I actually need   this Q_OBJECT macro, but I forgot it.    Let's imagine that I  added it, but I forgot to run QMake. So,   we add it back here. This is the most common  situation after this error. So, now we build. And, hallelujah -- a beautiful error message that  says something that is hard to understand. Let's   read the error message and see if we  can get anything out of it. It says,   "unresolved external symbol." First of all, this is  from the linker. So, the linker is trying to take   all the object files that it compiles from the C++ files and link them together into one binary.  "public virtual struct QMetaObject const pointer   _cdecl StopWatch::  meta -- just stop me, right?   What does it say? It says you promised me  that you would implement this method that   is called MetaObject that doesn't  take any parameter and that is const.   "I did? I'm sorry, I have never ever promised you  anything like that. How can you say that to me?"   Well, I'm sorry, you did because you added this  Q_OBJECT macro. Let me just go and show you   the definition of Q_OBJECT. This is  what Q_OBJECT looks like in your code.   It is one scary beast. Fortunately,  you do not need to understand it. But   please see here it says, "virtual const QMetaObject pointer metaObject," and that   is your void here, const. So at the second  when I added Q_OBJECT, I actually   did promise to do this. So, why doesn't it  work? Let me show you on the whiteboard. So, what I've drawn up here is the process of  running QMake and of running moc. So, we have our make   file over here. The makefile is of course the input  for make. That's what will compile our software.    The makefile is generated from  QMake by reading this Ex_Stop.Watch.pro file that we   created in our project. Of course, we created that  behind the scenes by using Qt Creator, or if   we used another ID, likely also created behind the  scenes. But that's beside the point here.   So, in my profile when I run the QMake step,   QMake reads the profile. It will   read which are the headers in this project here.  And each and every single header it will open   the header file and it will look for this Q_OBJECT macro. If it doesn't find   the Q_OBJECT macro, it'll continue  on. If it finds it, it will say, "Okay. Then..." and   it will write a target into the make file, saying,  "I need a moc_StopWatch.cpp," every   time this StopWatch.h file changes. So there's going to  be a target up in your make file for that. But as I   said, if there is no Q_OBJECT macro, we are  not going to have this. And then when I run make, I   will compile my steps. My StopWatch.h will promise  that there is this meta object method because   there is the Q_OBJECT macro that we  added. But given that it wasn't there at the time   when I ran QMake, this stage will not be there and  therefore we will get this error message when we   link our application. So, the cure is simple. All I  need to do is go up here, build, run QMake,   and now that it is run QMake I will press build again. It will compile it.   Press run and my application  is back in a working state. In my regular scheduled  trainings or on-site trainings   with this QML show here, I, at this stage, ask my  students (well, we have a reflection section after   the section and in that reflection section  I ask them), "When should you call QMake? And   at that stage, I hope that the student will tell  me, "Well, whenever you add your first signal or   your first slot, or really whenever you add Q_OBJECT to your class." But at some point,   one of the students raised his hand said, "Well,  Jesper, you should run QMake whenever the compiler   gives you an error message and you have no clue  what it is." I actually like that answer because,   rather than remembering exactly when just  whenever you see this compiler error about   missing whatever, whatever it was -- and it might  be different on your system -- at that stage just   remember run QMake or if you're in a CMake  build setup it has the same issue, just run CMake. And in this stage, it's pretty certain that every  single time somebody will raise their hand and say,   "Why doesn't it run QMake for me automatically?"  But think about it. What it would need to do   is that every time you change your header file  there would need to be a dependency for every single one of   your header files on your make file -- well, the other  way around. The make file needs to be regenerated   with QMake every time a header file is changed.  That would mean a lot of QMake re-running. And   even if QMake only takes a second or two, it would  be a second or two for every recompilation step,   something that at least the people in Trolltech  back in the day decided, "Hey, we're not   gonna waste a second or two for every single step."  And just imagine this was a complex CMake setup.   Those setups can easily take, what do I know,  10 seconds to run the whole CMake setup.   You definitely do not want 10 seconds for every  compilation or recompilation of your software, just   to avoid having to do it that very seldom  time when you add a new Q_OBJECT macro.   That's it for this video. In  the next video, we're gonna go   really deep into the machine room and  we're gonna watch one single class called...   well I'm not gonna tell you. It's gonna be  a surprise. But please do stay tuned and   please join us in the next video and please do  subscribe to our channel and for my daughter's   sake, please give me a thumbs up. Will you? See  you next time. Until then, have a great day!
Info
Channel: KDAB
Views: 1,698
Rating: undefined out of 5
Keywords: C++, Cpp, QML, Qt, KDAB
Id: K8U3-0I2iwI
Channel Id: undefined
Length: 8min 38sec (518 seconds)
Published: Tue Dec 22 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.