In this lecture, we'll talk about abstract classes. What is an abstract class? It's a class that can't be instantiated, but it can be the parent of other classes in a class hierarchy. We know we have an abstract class if we have one or more pure virtual functions in the class. What's a pure virtual function? It's a function that we define in our header file, but we don't provide an implementation of the function in our implementation or source file. Of course, that means we need to define the function using a particular syntax. Let's look at an example where this feature might be helpful. In this class hierarchy, we have the talker class as the root of the class hierarchy, and we have a happy talker and a sad talker. Each of those child classes will print either a happy message or a sad message. What that means though is that the talker class can't really provide a readable body for the say something function. It shouldn't say something happy because it'll be wrong half the time, and it shouldn't say something sad because that will be wrong half the time. What we really want is we want the talker class to not have to implement the body of that function, but to say any class that can actually be instantiated below me in the class hierarchy needs to implement their version of the say something function. So we're going to enforce the requirement that those classes have a say something function without actually implementing the body of that function in the parent class. Let's go see how this particular class hierarchy looks when we implement it in code. We'll start by looking at an implementation that doesn't use a pure virtual function. This isn't an abstract class yet, but I'll show you why we really want this to be an abstract class. Here, in my talker header file, I just have a virtual function called Say Something, and then in my implementation file, I implement the body of that function, but it's an empty body. In my happy talker header file, I'm overriding that say something function, and in my implementation, the say something function says, I'm so happy. In my sad talker header file, I'm overriding that say something function. Of course, both sad talker and happy talker are child classes of the talker class. Then in the implementation file, I'm saying, I'm so sad. In my main function, all I'm doing is creating a happy talker object, a sad talker object, and telling them both to say something. When I enter my code, that's what happens. The happy talker says it's happy, and the sad talker says that it's sad. The thing that we don't like about this implementation is this. Because we know in the talker class, that the talker class has no reasonable body of the function to implement. That's why I left it empty. We know it will never even get called or should never even get called. So we want to get rid of this because it's extra code that we know we don't want to use. Unfortunately, if we do that, we get an error message down here from the linker that says that it couldn't find a symbol for the talker, say something function, because we never implemented the body of the function. So we can't just get rid of it. We can, however, get rid of it and come over to the header file and turn this virtual function that we have into a pure virtual function. Which means that we're defining what the function needs to look like, but we're not implementing a body for it. The syntax for turning this into a pure virtual function is pretty straightforward, all we have to say is equal zero. That turns it into a pure virtual function. I can successfully compile now, and running the code has the exact same behavior as before. That's a win right away. We don't have to implement the body of this function, leading to extra code that we know will never be used. But there's actually another win as well. Let's say that my happy talker class, which says it's a child class of talker, doesn't actually implement, ''Say something''. I will comment that out there, and I'll comment it out here. When I try to compile, I get an error message here in my main function that says I can't instantiate an abstract class. That's why it's showing up right here as I try to instantiate an abstract class. Remember I said that abstract classes can't be instantiated. But you could certainly be asking yourself, why does the compiler think that happy talker is an abstract class? We didn't include a pure virtual function in happy talker, so why does it think that class is abstract? Well, the reason is because our parent class has a pure virtual function and we didn't override it. That means that that pure virtual function still hasn't been implemented. If we have a function that is supposed to be provided, but it hasn't been implemented yet, then happy talker also is an abstract class. We only get a non-abstract class once we reach a class that has implemented everything that is required in the class hierarchy. In this particular case, talker requires all its child classes or all its non-abstract child classes to actually implement the say something function. This is another really powerful feature of abstract classes, is once we specify here that all the non-abstract classes below us in the class hierarchy have to implement this function, we're enforcing a requirement for behavior in our children. As we often try to do in real life, we're enforcing our acquired behavior in our children, and if our children don't specify or meet that behavior, then they don't get to be instantiated. That is really helpful because as we move our way down the class hierarchy, if we forget to implement a function that's required, then the compiler will help us by giving us an error message and reminding us that we actually have to implement that. I'll uncomment this again because I want to give you clean code that actually works. We'll run it one more time and it behaves as expected. That's how we can implement abstract classes in our code. To recap, in this lecture, we learned we can use abstract classes to specify functions that are required in our child classes without having to implement the body of those functions in our abstract class. I will say that using abstract classes as appropriate leads to much better object-oriented designs.