Ever wondered how they maintain all the data and behaviors for the items in your inventory in a video game? Or maybe you've thought about how super-complex complex systems like banking systems, store management software, automotive digital diagnostic systems and tons of other applications were built? There's often a good chance that many of these applications use some form of Object-Oriented Programming. In this course, we look at Object-Oriented Programming, focusing on objects and classes.
Learning Objectives
- Understand how classes are designed and constructed and how objects are created from them
- Explore both the data members and member functions from which we build classes
- Learn how to instantiate classes as objects
- Learn how to use a rectangle class and a book class together and test them out
Intended Audience
- Beginner coders, new to C++
- Developers looking to upskill by adding C++ to their CV
- College students and anyone studying C++
Prerequisites
To get the most out of this course, you should have a basic understanding of the fundamentals of C++.
In the last lecture, we created a rectangle class. This was to reinforce some of our newly found skills in class creation to learn about UML class diagrams and to reinforce our knowledge of data members, constructors, getters and setters and other features of classes. In this lecture, we will continue building our skills and we will make a book class. For our book class, we want to keep track of the author of the title, the genre, and the number of pages. However, our book class is going to be immutable, meaning that unlike our rectangle class, once we have set the fields namely the author, title, genre, number of pages in the constructor, we don't allow the client code, which is the code using our class to change it. In other words, when a class is immutable, this means it lacks mutators. So, there will be no setters in our book class, just getters also known as accessors. Notice that we have a single constructor and that it is parameterized. So, that means when an object of type book is created, the client code must provide the author, title, genre, and number of pages as arguments. We don't have a no arg constructor. So, let's create a new visual studio project called Book Fund. Create a new project. Empty project next, and we'll call it Book Fun. All right, give it a couple of seconds. And as you may have guessed by this point, we're going to create three different files. Main.CPP to house the main function and test our book objects, book.h to hold the specification of our book class, and book.CPP to hold the implementation of our book class. Let's get the header, doing a slightly different order this time, header file book.h. Click "Add new item", book.CPP and of course new item, main.CPP i item main.CPP, Excellent. So, we're going to create the main skeleton first. So, IO stream and we're also going to include book.H using namespace standard. And let's write the specification file book.H first. This is where I like to start. I'll move some of the tabs around here. So, instead of proxima, once we'll put the include guards that we know. Across platform if in def and then define and then in def, excellent. So, since we're using strings in our book class, we need to include string library. And we'll create our class book here. What we got, public and again, I don't like the auto indentation and let's do this private and we will tap that in for the private data. We have string, author, the string title, string genre and int num pages. Now for the public we have the constructor of course, we'll start with the constructor. So, the single constructor with string author, string title, string genre and int num pages. We also have the getters. Remember no setters on this one. Get author, get title, get genre and get num pages. Now we need to provide the implementation of this specification. So, this time instead of retyping everything, I'm going to copy all of these and we're just going to use them over here in book.CPP. So, I'm going to do include book.H I'm going to paste these and there's a lot of errors right here, but that's because we need to fix it. So, the first thing I'm going to do is give them all bodies, so delete the semicolon and give them all bodies because I copied them from the header file, they still have the semi colon so I get rid of that, and then I give them bodies. Now the next step in this little copy conversion process here is that it doesn't know that any of these belong to a class. Now, this one is really confused about because it's like, I don't see a return type and you know, it has no idea it's a constructor. These right here may initially think that they are regular old functions, okay. So, we do have a couple of problems, we don't ever return here and we definitely have, we have the constant here which might make it think I don't know what that is. So, we do need to provide the name of the class and the scope resolution operator, so the two colons, scope resolution operator. I'm going to copy that, so I don't have to re type it and between the return type and the identifier of the method, the member function, the method, I'm going to put this class name and scope resolution operator, excellent so far so good, right? Now we can do the constructor quite easily. So, this author is equal to the author they pass in, these titles equal to the title they pass in. This genre is equal to the genre or style of book that they pass in, and this num pages equals the num pages that they pass out. The getters are quite simple. So, once we're done with the constructor, the getters are quite simple. We just return the author, for the title, we return the title, for the genre we return the genre, and for the num pages, get num pages we return num pages, right. Pretty simple implementation. You probably could have figured that out on your own, but a lot of this is very new syntax and we're still learning, so it's a good idea to go through a couple examples. But you'll definitely have a chance to prove what you know in the projects that are coming up because they will definitely use all of this class syntax. Now, remember we have all these getters, we don't have any setters, so once they're set in the constructor, when you initially create the book, you can't change the author title, genre or num pages because the class is what's our little word? Immutable, right. So, now let's go to main and we're going to test this out. I'm going to create a book we'll say Game of Thrones by George Martin. The title is Game of Thrones. It's actually a song of ice and fire of course it's a different but we'll just go with that. We'll say it's 864 pages, and then we also have math book James Stewart, very famous calculus book author, and it's quite a large book. And then we have CPP book, the famous CPP book by Bjarne Stroustrup, our inventor the father of C++. He's still alive, still doing a lot of work still and he still works on the. oh This is programming. He still works on the committee. I believe sets the standards for the C++. So, those are our three books, and I'd like to print information about these books. So, let's create a global function to help us because it's going to be a lot of repeated code if we don't. So, print book details. I'm going to create my little function prototype up here, okay print book details. And down here, I'm going to put that there and again we're using our little trick. Why is it a const reference again and not just book book because by default C ++, when you pass a parameter, it's passed by value. That means it makes a whole copy. Now, how does it copy the class? Well, it does what we call a shallow copy. It will go through and it'll basically copy all the data members over. And if it's a really big object, our book isn't too big, but it's, you know, bigger than a reference would be a reference, just basically takes up a memory address. So, that's on a 64 bit system without getting too technical. It's a 64 bit address or eight bytes. So, it's not really that huge, but it's got a lot of data in it that could be quite large. And this data is all way bigger than 64 bits right here. So, we make it a reference so we can get the advantage of the efficiency but we make it a const reference to make sure that you can't change the book because this function should not change the book. It has, it shouldn't be able to change it now. It's not going to matter in our case with the book because the book is immutable. All right, so for our purposes, it's just good programming practice and good convention to make it a const reference if we don't need to call centers. Since it doesn't have centers though, we would be out of luck anyway. So, what does this function do? So, we're going to print out book.getTitle and then we're going to say, so, title by with spaces on either side, the author's name, don't forget the parentheses. And then we're going to say space has space and then the number of pages, pages comma space, there we go, and then we're going to put and its genre is, this is like is it fiction? Is it a programming book? Is it a Math book? Things like that or nonfiction? Okay, there we go. and of course we have iostream and the print book details. So, this can use the cout. Now, we're just going to call printBookDetails on the Game of Thrones book. We're going to call printBookDetails again. Remember, reusable because it's a function. So, it's a form of software we use and then print the cppBook details. Now, to test all of that let's run our program. Debug, start without debugging. [no audio] So, we have Game of Thrones by George Martin, has this many pages and its genre is Fantasy. Calculus by James Stewart has 1,392 pages and it's genre is Math. The C++ programming language by Bjarne Stroustrup has 1376 pages and it's genre is programming. All right, good work. Looks good to me. So, we used a lot of what we have learned in order to make a solid programming project right here, a solid class. We even reviewed regular global functions and used a constant reference parameter. So, we took advantage of both the efficiency of passing by reference but with the added security of using a const reference instead of regular reference at least in theory in this case, remember it's immutable. Before we go on to the next lecture, I have a challenge for you, continuing with the same project, I want you to refactor the code so that a print book details method exists in our book class and then it prints to standard output, which again is the console. All the information that the global print book details function prints out, then comment out the global calls to the print book details and then call it as a method on our different objects. So, it's a big hint. Don't forget that this implementation in the implementation file will now need access to the iostream library. So, pause the video and give it your best shot. Come back when you're ready to see my solution. [no audio] How did that work out for you? This one wasn't a massive challenge but it did have some tricky aspects to it. And applied a lot of what we have learned. Let's do it together. So, we're going to comment out the usages of our print book details right there. So, Control K, Control C, remember that puts the comments around it or you can do it manually. It doesn't really matter, and inside of book.h we're going to add this as a method. So, void printBookDetails, and if you think about it, this doesn't need to change anything. So, it should be const. I'm going to copy it just to save me little typing time and go over into the implementation file. So, right here, and of course, in order to make sure that it knows it's part of the class, I'm going to copy the name of the class and the scope resolution operator, right there and it's going to do essentially what we did in the global version, which I can go over here and just copy it and then just change it over here in the implementation. So, let's do that. Now, you notice something, as soon as I pasted it, it underlined things like book and stuff like that, we'll take care of that. But it doesn't know what endl is, it says it can't find it and it doesn't know what cout is. So, can you think are we missing something? That's right, we need iostream in this file because it's in main, but we need it in this file. And we're going to do using namespace standard and then the error for that and for endl or at least gone. Now, you might think why don't I put include iostream over in the .h file, and the answer is if you're not using it in the .h file, it's considered better practice to only put it in the file where you actually need it. Now, if I'm using string, which I am here, the reason I put it in here and not the CPP files because when I include it in here, it's needed in order to indicate the return types here and also the data types of the private data down here, and in book.cpp, I don't have to include it again because when I include book.h that also since it includes string, gives me access to string in here. I hope that makes sense. You only need to put it in the file where it's accessed or the top most level file where it's accessed. And in here we only needed it in here, we're not making reference to cout in book.h. So, we only put it in here. Now, we've got to fix the code here. So, the global version took a parameter and we don't need a parameter here, whereas we needed it over here. So, we got rid of the parameter and we don't need book.getTitle. We're inside the class now. So, we have direct access. We could call get title if we wanted to but we have direct access to the title, the author, the number of pages as private data, get rid of that, be right there, and then of course the genre. All right, now we need to re-factor main so that it uses this newly created method. So, we have gameOfThrones as one of my books dot, there we go printBookDetails and now mathBook.printBookDetails and then cppBook.printBookDetails. So, we've refactored it from using a global function which takes the book as an argument and instead we are using a no org or no argument method on each of the objects. Now, which one is better? Well, that really depends on your situation. I'd say for this one since we're only using the book in context of console output then it probably makes sense to make it a method. But it really depends on your situation. It depends on the design, it depends on the needs of the software and other things. All right, so just to show that we actually have the same output after modifying our code to have these member functions or methods. Let's run it again just to make sure everything is good. And it is, prints out exactly what we expected exactly what we had before. Awesome work everyone. We have successfully refactored our program a little bit by adding some of the appropriate functionality to our class and pulling it out of the main file. We've also expanded our knowledge of working with classes, practicing several of the features of classes and objects that we've dealt with throughout this section. We've also learned about immutability. How do we make our classes immutable? We don't put centers. In the next lecture, we start working on this section's projects with a bank account class. I'll see you there.
John has a Ph.D. in Computer Science and is a professional software engineer and consultant, as well as a computer science university professor and department chair.