 Hey everybody, this is Brian, and let's continue our conversation about the QObject class. Specifically, we're talking about automated memory management, or if we click more down here, QObjects organize themselves in object trees. What does this really mean? We're talking about automatically deleting its children. If you're a parent, I think that at some point you've wanted to delete your children, but that's not really as violent as what we're talking about. We're talking about automatic memory management. If you click on this object trees link, you can read this pretty lengthy little article here, but we're talking about ownership. I covered this pretty in-depth in my understanding QObject in Qt, on medium, scroll down. There's a nice little graphics here. There we go. We just simply have a parent-child relationship, and children can have children and so on and so on. The premise being we're making an object tree, and when the parent is deleted, all of the children and their children are deleted as well automatically. It takes the headache out of memory management, and it just makes it ridiculously simple. I absolutely love this. You can actually, like if you delete this guy, it'll delete these, and it will take care of the ownership for all that as well, so you don't have to worry about this object tree. It's all baked right into QObject. It's very streamlined, very easy, very elegant. I have to apologize. It's been a minute since I've submitted a video, and here's why. I hit the submit button on the Qt 6 core for beginners with C++. I'm so excited. I can barely pronounce it. You notice this says this course is in draft mode. It's not available yet, but hopefully fingers crossed the next few days they'll approve it, and this course will be a direct replacement for, scroll down, the Q5 core for beginners with C++. If you already have this course, you're going to get a free coupon as soon as they approve it, but anyways, let's dive in and let's take a look at the parent-child relationships. Okay, before we dive in, we've got a little bit of setup we need to do. First thing we're going to do is add a Q timer. So I'm going to say include, Q timer, and if you don't know anything about Q, basically what this will do is fire off some sort of event at a specific interval, or we can do what's called a single shot, which we'll do it one time. So we're going to go down here. There's something we need to understand before we really continue, which is Q core application is, well, a Q object, and just simply hit F1 on the keyboard, and you can see everything about it right here, and it is inheriting Q object. So because this is a Q object, we can use that parent-child relationship. So your very application can be the parent. Also understand that A.exact is Q core application exec. So if we highlight that and hit F1, what exec is doing is entering a main event loop. What does that mean exactly? So if I save this, run it, give it just a brief moment for this little virtual machine to build it. You notice how it doesn't say hit return to exit, or the window doesn't disappear. Just sitting there. That's the event loop. So we're going to include a timer to shut this down. We're doing this because we want to see the full lifecycle of a Q object. So I'm going to just say Q timer, and let's call this timer, then timer dot, and we want a single shot, meaning we're going to do this exactly one time. We're going to cover Q timer in depth in a later video, but I just for demonstration purposes wanted to do it here. We need in milliseconds, so I'm going to do 3000 milliseconds or three seconds. And then notice it wants a Q object receiver and then a const care member. So what we're doing is signals and slots, something else will really cover in depth, but just at the moment, take a giant leap of faith that we are sending something to another Q object. So the timer is going to let the application know the time is up in three seconds. So we're going to say address of our application. And then let's go ahead and give it Q for application. And we need a slot. So you may be wondering what a slot is because we haven't really talked about it. So a slot is a normal function that has mock wrapped around it. So we can now use what are called signals and slots, and we can send messages back and forth between objects. We're going to cover that very, very in depth in a later video, but just understand what we're doing. So the timer, after three seconds, is going to let our application know it's time to quit. It will exit this event loop. So what we want to do now is grab this, and we want to just intercept this somehow. It's an int. Let's call this value equal a dot exact. So what this is going to do is give us the exit code of our application. That exit code is something our application is going to return out to the operating system. So we're just simply intercepting all that. Once we got that, we can just say Q info. And let's go ahead and print out the exit code. This is so that we know we shut our application down gracefully. Save this. Let's run it. And as soon as this thing runs after three seconds, it should automatically shut itself down. There we go. So we have our exit code of zero. Zero is the operating system's way of knowing this shutdown as expected. There were no errors. So far we have our application. We have a timer with a single shot. So after three seconds, the application automatically closes. What we're going to do now is create a class that allows us to set up a parent-child relationship. So I'm just going to right-click, add new, C++ class, and then give it a name. Base class, we want to make sure we are Q object and automatically Q creator is going to include Q object and add the Q underscore object macro. This little guy right here is super, super important. Without that, it's not officially a Q object. This is what Mock uses to determine that our class is actually a Q object and it sets up all that goodness in the background. Those are the file names it's going to use. And there's a path that's going to set it up in just next, next finish. And let's go ahead and jump in here. And we're just going to add our class into CMake. I love you guys, but pretty please automate that. It's kind of annoying. I've had a few people already ask me, hey, how do I set that up so it does it automatically because everybody's so used to CMake? So in here, we're going to add in Q debug. This is what's been letting us print out into the console. The major takeaway from Q debug is that it is basically see out on steroids. You can intercept this and set different levels and things like that. All right. So let's jump in here and we're going to do a deconstructor. And then we're just going to right click refractor and then add definition in our implementation file. So you notice right off the bat, we have constructor and a deconstructor. So we have our objects full lifecycle here. This is where I'm going to do just a smidge of copy and paste just to save a moment of time. And let's call this deconstructed. Notice something right off the bat. Constructed and then parent. So we are inheriting Q object and we're going to get that parent. So there's our object tree and this is in the constructor. And in our deconstructor, I want to also know the parent. Notice how it's saying, hey, it doesn't know what this is. So we have to actually call the getter. So we could say this parent and it's actually a function. Don't need to this keyword. I just wanted to illustrate that. So someone out there is going to just copy and paste it down there and then wonder why it magically doesn't work because you have to call the function to get a pointer to the Q object. All right. Now that we've got that little beautiful thing in place, we can start looking at how to observe the tree and the object lifecycle. Back in our main code file here, we're going to go ahead and include the class we just created. So I'm saying include, we want test.h. Now what we want to do is make a function. And this function is going to be used for setting up in the constructor. So I'm going to say test. Notice that's a pointer. And from here, I'm going to say Q object, not Q object macro. I want the actual Q object. And let's call this parent. What we're going to do is just simply return a new test class. And we're going to set that parent in the constructor. Notice what we're doing though. If you're normal just C++ programmer and you've never worked with Q, you honestly look at this and go, you have just created a memory leak. But we actually haven't because we are setting that parent child relationship. So the parent, when it's destroyed, will automatically destroy this right here. It's actually really cool. I like this. So let's go ahead and jump down here and let's demonstrate that. So we're going to set it up in the constructor here. I'm going to say, let's call this test. Dog equals and we want to get our test. And we need a parent here. So the first thing we want to do is decide what object we want to use as the parent. Well, remember our Q core application, our very application is a Q object. So we can just simply use that. And that's exactly what I'm going to do here. So I'm going to give it the address of that. Let's go ahead and set the object name here. So I'm going to say dog dot that object name, just so we can see what that is in the console. And let's call this, I need a good dog name about spot. I was going to say something like Thor or Zeus or some, you know, Greek God or something like that. But spot works just fine. So let's go ahead and save and run. And let's demonstrate what happens with the parent child relationship. 1,002, 1,003, the application shuts down and bang, spot has been deconstructed automatically. We don't have that memory leak. We don't have to worry about it. All of this cleans up automatically. So this automatic memory management through a parent child relationship is very easy and very powerful. We don't even have to really worry about pointers as long as we're inheriting Q object. But the question is going to get asked, what if you don't have a parent? Let's go ahead and demonstrate that. So I'm going to grab this whole thing. And yes, all you C++ experts in the comments, there's a million ways of doing this. So I'm going to say setting up after the constructor. We could very easily just set this to null pointer. But I want to very clearly for the C++ newbies out there, show you, there's no parent here. So setting up after constructor, the get test, no parameter is going to just simply return a Q object with no parent. This is a problem. This is a problem because this is what's called a memory leak if we don't manage this memory. Go ahead and scroll down here and let's demonstrate this. So I'm going to grab this guy. We have our application and then we have our dog. The dog is a child of the application. I'm going to just grab this and everybody who watches my channel knows I love cats. I actually love cats and dogs, but I love cats really like a lot. So anyways, we've got this cat and we're going to call get test with no parent. And let's set the name here. I need a good cat name, princess. I think every cat should be named princess, male or female, doesn't matter. All right, so now that we have this, you notice we have a problem. This isn't in our object tree, so we need to set it in the object tree. Sounds super scary, but it's ridiculously simple. We're just going to say cat.setParent. And you notice it just takes a pointer to a key object that we want to set as a parent and Qt takes care of that entire object tree for us. I love it. It's just absolutely ridiculously simple. So let's go ahead and use our dog. So now we have a clear object tree. We have our application. Application is the parent of the dog. The dog is the parent of the cat, which is really a weird thing that I think about it. Let's go ahead and save and run. And let's watch all of this happen in three, two, one, boom. Application shuts down. So we have constructed our dog. Its parent is the QCore application. We've constructed our cat. It has no parent, it's just a zero, zero. And we have an exit code of zero, meaning we shut down gracefully. And then you see our dog, Spot, deconstructed. Now our cat, Princess, also automatically deconstructed. Its parent was the dog. That is extremely cool. Wrap this video up, let's cover one more final thing. It's really great that we have this object tree, but how do we access the individual children in that object tree? We've been using our test class. I'm just gonna jump out to the implementation you see in our deconstructor. I wanna know just before we deconstruct what children we have. So I'm gonna jump in here and say four each and I want Q object pointer. Let's call this child. You can call it whatever you want, but let's call this one child. And this is going to be in our children. Now you notice how there's children, fine child, and fine children. So these are a little bit more advanced than where we are in this video series. We're just gonna call children, which is going to give us a Q object list or a list of Q objects. Go ahead and do this, and I just wanna Q info this out. And this basically is just gonna show us what children we have. So I'm gonna say the current object, and then I want to know this is a child. And then let's go ahead and print out the actual child object here. Save this, let's run it. Now remember we had our application which had a dog, the dog had a cat. So sure enough, we can see right here, bang, spot as a child named princess the cat. Now you can actually access your elements inside that list. It's ridiculously simple. And yes, you can just keep adding and adding and adding and you can even remove them. When you actually delete one of these objects, it's automatically deleted out of this tree for you, so you don't have to worry about it. I hope you enjoyed this video. You can find the source code out on github.com. If you need additional help, myself and thousands of other developers are hanging out in the Voidrealms Facebook group. This is a large group with lots of developers, and we talk about everything technology related, not just the technology that you just watched. And if you want official training, I do develop courses out on udemy.com. This is official classroom style training. If you go out there and the course you're looking for is just simply not there, drop me a note, I'm either working on it or I will actually develop it. I will put a link down below for all three of those. And as always, help me help you. Smash that like and subscribe button. The more popular these videos become, the more I'll create and publish out on YouTube. Thank you for watching.