Now, in order to build inheritance in a way that supports pure polymorphism. It's a term I was using earlier. We need a concept called a virtual function. A virtual function is going to be a function that's declared in a base class, and re-defined in the derived class. The right term for that redefinition is going to be called overridden. And overridden is not the same as a re-definition that we were using to, when we had several signatures for the same function like sort or print. So overridden, we keep the signature. We change the definition, but what triggers the use of the new definition is where you are in the type hierarchy. Where you are suppose to the signature, it's basically that this pointer. So that this pointer, lets you to decide on selection and that has to be at run time. The class hierarchy defined by public inheritance creates related types, all of whose objects can be pointed at by a class, a base class pointer. So there's going to be a very simple idiom to decide how to run a program in which all the objects are coming from a single type hierarchy and have virtual overridden methods. And that's going to be through a "this", through a pointer through the base class and then depending on what that pointer sees, what kind of sub-type there is dynamically at runtime. It'll select the appropriate function. And this is, this mechanism it's called pure polymorphism. Runtime dynamic. It's a dynamic selection. By the way, since it's dynamic, it involves a small overhead, small run-time overhead. RT for run-time overhead. And that's a reason why not everything in the C++ community is virtual. If you look at something like Java, basically, Java is all virtual functions. And that's the common case. However, C++ still tries to maintain super efficiency. So if you don't need the dynamic selection, which involves carrying around some tables at runtime. Referencing the runtime tables. You can avoid that then you can avoid it through non-virtual member functions so that they're not overridden in the successive inherited classes. It makes the language more complicated, but it also gives you more tools in your tool bag to have things efficient. So let's go back to our points, to our example. And let's go and see what we could do with further inheritance. In this example, we're starting with a point, which was a two dimensional point, which inherited from duo. And then, we're going further in the hierarchy so the hierarchy looks like this duo up here, a point is a duo and then a point3d. Is a 2d kind of point with another dimension. You could see it here in this constructor. If you look at this constructor, it uses the base class, constructor So it's default base class constructor on point, and then it adds a z value. In this case, the value zero. So basically, the initialization is going to end up being typically zero, zero, zero a standard initialized. A three dimensional point, unless we have two dimensional values to it. And we would, this is just you should be able to if you want, extend this by writing other constructors, so again, I, it's very worth your effort to do duo point 3d point and play with all this to see how inheritance works. And here, we've had a virtual function, what used to be non-virtual, we've turned it into a virtual function so that it could be overridden. I didn't on the last slide. Remember, what we're used to is signatures is overload. And that's where we get signature match and if overridden, we're, we're using "this" pointer. And notice what we've done, we have the square root now of all three. The first, the second and then the z value. And we've added this further private part. Now, in the main part of code, we would see what would happen when virtual. Three and four is going to give rise to five. But if we had a 3d point, and we set the 3d point values to five, six and seven. And we ask what the length of the 3d point was, we would be invoking the virtual mechanism, and this length is not that length. These are different. This is overwritten. So it's really using scope resolution. We're really invoking the overridden length method. And if we squared that, and squared that, and squared that, we'd end up with and take their square root, we'd end up with 10.488. That's the three-dimensional length in three space All of this could be done via a pointer logic. So if there was a point at both a 3d and 2d pointer forms of points, and then this kind of pointer selection would be what's called pure polymorphic. It would pick the right one. The right length, either the two-dimensional calculation if it was a 2d point, or three-dimensional calculation would be done. So we could have them all mixed up and run some piece of code and allow dynamically, the right thing to get done. Pure polymorphism. The object being pointed at must carry around type information, so that the distinction can be made dynamically. This is your typical OOP code whether you're in Java or in modern day Python, or any other of the major modern OO languages, (such as) C sharp. Each object knows how it's to be acted on. So, that's a compartmentalization. In a way, if I know what the action means, then I can get it right, I can have it tested. It's actually the basis of something called unit testing. You keep everything close to the individual element that you're developing, and it just makes extending big pieces of software, it compartmentalizes it. It allows the software to maximize reuse. It also allows a natural model, a taxonomic modeling of the problem domain.