Hi. I'm Jesper Pedersen, from KDAB. You're
watching Programming with Qt and QML. It's not going to feel all that much QML in this
video because we're down in the machine room of Qt, looking at the C++ side of
things. We already started, in the last video, to look at what signal/slot connection looks
like. In this video, we're going to look at two different versions of signal/slot. We have
a signal/slot connection where we connect with a PointerToMemberFunction. That's what
you saw in the previous one, and then I'm gonna show you what it would look like and what it felt
like to be a brave man in the good old days -- Qt 4 days when we had signal/slot connection with
a macro-based version instead. That's the reason why I showed you that. So, don't worry. I didn't lose my mind
yet, or at least that's not the proof that I did. We have three different ways to connect signals
and slots in C++: function pointers, signal/slot macros (the
macro-based versions), and then we have the function objects (and the most noticeable version of that is
called lambda expression). We're going to see the lambda expression in much more detail
in the next video, but in this video here let's look at the two different ways that you can
connect where we are not talking about lambda expression. The first one is what you saw in the
previous video here. You write the object that you want to connect from, the PointerToMemberFunction (so QSlider::valueChanged), the object that you want to connect to, and
the slot that you want to connect (so &QSpinBox::setValue). And the syntax for
your connect statement, if you go and look in the header file, looks exactly like this. It's a
const QObject pointer, and then a PointerToMemberFunction, and a const QObject pointer
again, and a PointerToMemberFunction again. We have another version of doing it and
this is what we did back in Qt 4, Qt 3, Qt 2, and Qt 1. We used some macros instead of this PointerToMemberFunction and actually you might even want to use that in Qt 5 if you want to, Qt 5, 6, or
earlier for some specific examples. But I'll point to that exactly when we get there.
The PointerToMemberFunction, again, takes four fingers. So, who is submitting a signal, which
signal, who is emitting or who's receiving the who is implementing a slot, and which slot are
we talking about. Back to that one, the second and fourth are not a PointerToMemberFunction this time. They are just a regular string. You can see that up here: const char pointer signal,
const char pointer method. And the way we get to those strings is that we write signal in capital
letters around the name of the signal, and then in in the parameter list. So, we're talking
about the one bringing out the integer, connecting to this slot, "s-l-o-t," slot here in
capital letters, the name of the slot and again it's parameter best. And that's where, if you are
in Qt 5.6 or earlier, you might want because it's easy to specify which signal and which
slot am I talking about. You simply do that with the parameter list. So, if you had a slot
that took both an integer and a QString, you could easily tell it, "hey, it's this one that takes
an integer," and we'll see that in the next example. The signal/slot mechanism, let me just bring this
up for you here, so I got this simple example here. Got lots of errors; wonder what
Qt Creator is up to here. We're in C++ level now, so I need to compile it,
configure here now, compiling it and running it and running it, I said. There we are. Oh...there
we are. Thank you very much! Here, I have a QSlider that is connected to my QSpinBox, and
when I move it around you can see it works just fine. I did so using this syntax here from my
Qt 4 days of SIGNAL valueChanged int comma spin comma SLOT setValue, but just imagine that
I made a small spelling error here valueChange instead of valueChanged. Let me compile that again.
It's already doing that; it's coming up there. And did you see a difference? What?
Let me show you the difference. Aha! Not working, huh? Well, why didn't I get a compiler? Why
didn't I get anything? Well, you did -- L3 over here, L3 your Qt Creator and down
here you can see "QObject::connect: No such signal QSlider::valueChange (int) in," this particular line. Obviously, our C++ compiler
does not have a chance in whatever to be able to take that string that it got and
look at whether it's really a signal from that object. That's why the PointerToMemberFunction
was welcome so extremely much in Qt 5. Because, finally, we got something to give us a compile
error. It's not even a runtime error when you start your application. It's a runtime error when
you do your connects, which could be several hours into using your application. And, at that point, it
will print out a standard output and error message, and if your customer is in Windows without a
standard error output or if your customers even are on Linux but it compiled in a way where they
do not see the standard output...game over! They will simply not see why it doesn't work. They will
only be able to report back to you that, "hey, this slider here doesn't work at all," and you'll have
to investigate. So the Qt 5 way is, by far, preferable. There is another disadvantage of the Qt 4 way, namely, that there are no implicit conversions going on. So, you cannot
connect a signal that brings out an integer into a slot that takes a double, even
though we all know that, if the integer is within a given range, that should be just fine. With the Qt 5 macro bay or the Qt 5 PointerToMemberFunction connect, it works just fine. There is a final thing to say that's this one down
here. It's actually an argument for why our new way is worse than our old way of connecting.
Fortunately, in Qt 5.7, it was fixed. So, let's try and run this example again. I need to compile it. I
need to configure it first and then I'll compile it, and we'll see what it does. Well, while we're
compiling, I can tell you it's a slider that is connected to a QLCDNumber. It's not more sexy
than that. But what we'll see is that my connection now looks like this. It is truly terrible, and part
of it is hidden behind my face. So, there we are. I have a connect statement, a slider as who's
emitting the signal. It is the valueChanged from QSlider. Which object? That's the integerLcd.
And which slot are we talking about? Yeah, about
that, we would like to say that it's the QLCDNumber::display, but let me show you
the documentation. QLCDNumber::display takes a QString. No, no. The QLCDNumber::display takes an integer. No, no. The QLCDNumber::display takes a double. So we have three overloaded methods: one taking an integer, one
taking a double, and one taking a QString. So your compiler at this time will not know
what to do. If you're gold, you would likely end up on a page that says, "hey, you should do exactly
this syntax here," which is what we had to do in Qt 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6. But, fortunately, in 5.7, the solution came around. Let me show you what your compiler
is going to tell you. If you forget about this or, while forgetting is such a strong thing, if
you just set up your signal/slot connection and you didn't think of how it is going
to be an overload here, then you would write like this, instead. Let's compile that and see what
our compiler buffs at us. It will say, "no matching function for call to 'connect.'" The candidates were this
one, this one, this one and I also got a candidate. This is a time where I just have an urge
for sitting somewhere where it's nice and warm and I can have my feet in cold water and
possibly something to drink with me, because this is just the most annoying error message of
them all that comes at you there. And the first 20 times you see that, you're just like, "hmm what was that
again?" And, hopefully for you, you'll end up on a stack overflow page that tells you that horrendous
syntax that we had before. But, hey, if you are one of the cool kids that is using Qt 5.7, then you
got two other alternatives. Let me show you those. The first alternative, if
you're using Qt 5.7 or above and you're using a C++ 11 compiler but not
C++ 14 available compiler, is you write QOverload and we're saying we want
the int version, ::of, and that's where you're looking at me in total
disbelief and saying, "yes, but seriously you think that's better than the other version?"
Yes, I do. It takes a bit of getting used to, but after seeing it five times, even somebody
like me can remember to write it. So, before I brag too much, let me just validate
that it actually does compile. So QOverload::int, I'm talking about the
overloaded version of display that takes an integer and then the colon colon of -- template
magic for making this work. This is if you're using qt 5.7 or above and you're using a compiler
that's still not C++14-capable, if you're using a C++14-capable compiler and welcome
to the future! This is 2019; it's gonna be 2027 when you watch this, I'm sure. This is going to be an
everlasting video. You should have C++14, and if you do, then you can write syntax looking
like this. Instead of the capital Q, you're going to write a lowercase Q that looks so much
better, right? Well...and the colon colon of also goes away -- so qOverload, lowercase q,
and here is the list of parameter. Had I wanted to talk to the double one, it would look
like this. Had I wanted to talk to the QString version, it would have looked like this. But, as
you know, I want to talk to the int version, so it looks like this, and here's my connect
statement with a much easier reading syntax. That's it for this video. In the next video,
we're going to see how we can connect our signals to lambda expressions. There's been
quite a bit of debate over the years of when you should do this and
is it a good idea, and so on. I'll give you my personal assessment
on it when we get to that video. So until next time, do subscribe to our channel.
Will you? And have a great day.