Practical Polymorphism C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello in this video I'm going to look at using polymorphism and object-oriented programming to make our application development simple and I'm going to demonstrate that through the use of a simple computer-aided design like application but you may have noticed I'm not in my usual programming place well it shouldn't be of any surprise to you that I'm actually full-time employed and sometimes my job requires me to go out on the road and stay in delightful hotels such as this one nobody ever said programming was glamorous I'm travelling around with work like this has completely ruined my YouTube schedule for the year so those of you expecting to see an update to the top-down city based car crime game well I might tag something on at the end of this video if I've got a couple of minutes to spare however that's been delayed a week so this video I thought be useful to do something to enhance sort of the C++ basics and we'll look at polymorphism a very useful technique now I thought to be different instead of using games to demonstrate polymorphism I'm going to create a small application a very simple CAD package so here I've got a matrix of dots which the cursor can clamp to and we can see we've got some axes and the middle of these axes represents 0 0 in our world now if I press a particular key I can start to draw a shape and we'll see two little red dots that allow me to manipulate the shape so though we've got a box and here I can draw some lines just throw them around all over the place at the moment and we can draw circles too and see the radius is a line surrounding by circle shape there's some other nice features too I can zoom in and pan around now of course we've done panning and zooming before so I won't go into too much detail about how I do that in this video and I can also place my cursor over any of the red dots and tweak the shapes positions oh yeah before I forget there's one more shape too and this is a multiple construction shape that gives us a spline so we can define curvature very nice and you might be thinking well what's this got to do with polymorphism well it's difficult to graphically show polymorphism but here all of the shapes are effectively the same object to the code underneath of course the shapes are unique in that they are circles and squares and lines and splines but the code that we'll handle these shapes doesn't really know about that and it doesn't care either which means making our application can be quite a simple process because instead of trying to handle all of these different shapes uniquely will let polymorphism do it for us now some of you not familiar yet with polymorphism may already be thinking of ways to handle this we could have lots of objects for all the different types of shape and our applications sort of interrogate those objects one by one depending on how it should be manipulated or drawn to the screen perhaps another solution is to create one type of object which is all of the objects and the objects itself can self determine what to do in a given scenario approach is like this are valid but they can be a bit messy and we may as well use the tools that C++ provides for us to do this and the primary tool and what this video is about is polymorphism will engineer our code in such a way that the compiler can decide at runtime which methods to call what shapes to draw and how things should look now I will start by saying that polymorphism is not a beginner topic although the way I'm going to show it in this video we're really only going to start looking at it at the most top level object-oriented programming and polymorphism is a really rich and detailed topic in its own right but you can achieve quite powerful things just by knowing the very basics for this video I'm going to assume you do know a little bit about classes already and although polymorphism does exist in lots of different languages I'm going to be specifically looking at C++ let's start with a simple class in this case called a and a has a function called do something what the do something function does depends entirely on what class a is now I'm going to assume that we have a set of structures in our program that are all quite similar in nature ie they have a lot of commonality between them so I'm going to try and package that commonality up in Class A to turn it into a base class this of course means I can derive from my base class more classes in this instance Class B Class B inherits all of the methods and attributes from Class A assuming that it can do to whatever access specifiers we've determined are on those properties of Class A but let's for now assume that everything is public and easily accessible if I create an object of type B and call the do something function then that do something function is defined by the base class a I can of course override that do something function by simply redefining it in Class B now if I create an object of type B and call the do something function it will call this one instead and it goes without saying that if I create an object of type a and call the do something function it will call this one perhaps I have another derived class class C well exactly the same thing applies this two could have its own do something function so far so good nothing out of the ordinary but we started this with a particular caveat and we said that these classes that derive from Class A were in some way similar and we created Class A as a base class to encapsulate the common functionality between the two derived classes and in applications it's useful to group things that are similar together and so how can we do this if I create an object of type Class A it is very clearly defined as big of type A likewise if I create an object of type B it is very clearly defined as being an object of type B it is not an object of type A even though B inherits from a it is defined as being B naturally the same also applies to an object of type C when we want to group things that are similar in C++ we have several ways of doing this one approach is of course to use an array but whenever we specify an array all of the elements of the array are of the same type perhaps we could use a vector but again the same problem applies we have to nominate a type through our vector in fact any of the standard containers will have the same restriction the convenient thing to do is to hint to the compiler that B and C are in fact derived from a and the town factor an array only stores elements of type a well this is quite nice and we're almost there but if I wanted to use a specific element of our vector of type a and call out do something function as we saw before it's going to call the do something function defined by class a we've still not got the flexibility implied to look at the derived classes that's because all of our objects are of type a instead I'm going to do something that appears a little strange I'm going to create an object of type class a but I'm not just going to create an object I'm going to create a pointer to the object so this means now when I'm creating a new object I need to use the new keyword or a smart pointer equivalent but now I can do something a bit special because B and C were derived from a and all I'm storing is a pointer to where a might reside in memory I can actually create a new object B and of course I can do exactly the same for my Class C type so now when I create my vector to hold my similar objects together I'll make it hold some pointers to Class A and threw some smoke and mirrors implemented by the C++ compiler what we are implying here is as if classes B or C override a method in Class A then if we were to call such a method in this case our do something method that it will call the appropriate method related to the class that was constructed and that's quite a complex and powerful thing I can now store in a single container a group of similar objects that all have unique functionality but a common interface in effect we've allowed the base class a to morph into multiple subclasses hi polymorphism we have eliminated the need to manually check what the type of each object is and perform the required functionality we're requesting at that point in time but it's not quite as simple as I've just made it out to be we need to hint to the compiler which functions were likely to be overriding here is a very simple class definition four type-a we can see I've got the void do something method that's the one we've been trying to override with us subclasses if as before we just directly called the do something method on the object stored in our vector regardless of whether that object was of type B or C it would still call that do something method related to Class A we need to tell the compiler that do something is a candidate to be overridden by a base class and we can do that with the virtual keyword this hints to the compiler that I may be overridden if I'm not overridden then any call to the do something function will naturally be implemented by the base class ie whatever code is written here so if it is overwritten it'll execute the overwritten code but if no override is provided it'll execute this default code and there's one last philosophical thing to think about here it may be the case that Class A on its own doesn't make sense the sense only comes into it once something has been derived from Class A ie we've created classes B and C in which case Class A is really just an interface to its subclasses on its own it can't do anything useful and we'll see an example of that in this video well instead of providing some default code that doesn't do anything and to force the programmer to provide an implementation when anything derived from this class we can tell the compiler that this class is an abstract encapsulation by defining our virtual method here as being pure and you can't create an instance of an abstract class so if anybody now tries to create an instance of type a it will fail and throw an error to the programmer because no implementation of this function exists even though something potentially can call it and so this is a very powerful and useful way of wrapping up your program structure now I appreciate to some of you this may all seem incredibly alien but don't worry I think the example code that's coming up really shows the power of this nice way so let's briefly take a look at the class structure for the CAD program I demonstrated at the start I have a base structure called S shape and from that basic structure I derive unique classes that represent the shapes that I have so a line a box a circle and a curve all of these things are indeed shapes so it's very useful to recognize them as a singular shape but they look differently so I want each of these classes line box circle and curve to be responsible for drawing itself so they will all have a method draw which draws it to the screen so it seems that draw is a great method to be thrown into the base class the shapes are fundamentally defined by nodes points in 2d space and the curve is the oddball one here as its defined by three points in space so all of my shapes are also going to have a common vector of type s node a simple structure and our node will contain the X&Y position of its location in space and a pointer to its parent and this is so when we select a node later on we can immediately get access to what shape is it connected to a valid thing to shout out here would be put Chabot we're talking about object-oriented programming why are we not using classes well classes and structs to the C++ compiler are absolutely identical except for one thing and that is the default access method first struct all properties and methods well they're public and for a class they're all private and so it really doesn't matter unless you're an object-oriented programming enthusiast naturally I'm going to start by using a skeleton OLC pixel game engine program and if you've not heard of the pixel game engine it's a very simple technology that I've created that allows you to draw things to the screen quite quickly and simply and I'm going to construct a pixel game engine quite a high definition one on usually this case it's going to be 1600 pixels by 960 pixels and there's going to be a one-to-one relationship between pixel game engine pixels and screen pixels I have my traditional on use create and on user update functions and right now all on user update does is grab the mouse coordinates on the screen and stores them as a floating point 2d vector you saw in the preview at the start of the video that we can pan and zoom around the screen and I've already got a video that's just about this topic so I'm not going to go into very much detail here in fact I'm just going to bring that code in and convert it to use our new vector type that we added in the last video I've also added a couple of other features to the pixel game engine including the ability to draw dashed lines which will see a little later on and that long last mouse wheel support the first thing I'm going to do is set this up to enable the panning and zooming and drawing of the axis in the world and none of this is new stuff in fact I've done a video precisely about this topic which you can click in the little link above but to facilitate panning and zooming we need to store some world's transformation variables and for this video I will be going quite quickly through this I've created numeric vectors that store the position of the offset and the start panel location we also need a variable to handle the scale for the world transformation finally I'm adding a variable called grid and this is the spacing in world space between points that we're going to see on the screen so all of my points are going to be one apart now panning and zooming is all about transforming things from world space to screen space so the first functional add directly copied from the panning and zooming video and modified to suit the new floating point vector type is world to screen that takes in a vector in world space and gives me two screen coordinates as an output we also want the inverse of that screen to world I'm going to set the default offset for our panning parameters to be the middle of this screen width and height so that puts zero zero in world space in the middle of the screen everything else is now calculated per frame in on user update once I've got the mouse coordinate I'm going to enable zooming by scrolling the wheel but panning by holding down the mouse wheel and moving the mouse so I want to be sensitive to the mouse wheel being pressed and that's going to store the start panel location as I have the button held down and move it around want to update my offset so let's see quickly about drawing the world firstly I'm going to clear the screen and because I can see into the future I know I'm going to need some temporary integer coordinates to represent locations in screen space we only want to draw what we can see traditionally so I want to work out what the visible extents of the world are and to do this very simple I simply use our screen to world function with the top left coordinates of the screen and the bottom right corners of the screen and this will give me the dimensions of the visible world in world space I want that to be a little bit of overlap around the edge of the screen just so when we're drawing lines we don't see them clipping so I'm flooring the left and top values and I'm taking the ceiling value ie rounding up the bottom and right values because I know the extent of my visible world I can simply have two nested for-loops now that iterate along each axis stepping in my grid size because now we're iterating through world space my grid was just set to one but I'll use the world to screen function to change this world space coordinates into the screen space coordinates and use that location to plot a pixel safe in the knowledge that it doesn't matter where I am in the world I'm only drawing what the little window of the screen can see into that world I also want to draw some axes into the world so I can see where my zero zero location is and I'll do this by extracting a line from world space based upon the visible extents of the world and I'll capture those in screen space in the SX sy e ex and ey variables and it's simply a case of drawing a line between those two coordinates and I'm going to draw it in gray but I'm going to just quickly and very sneaky show you a new feature that I've added to the pixel game engine which allows you to draw lines with patterns and in this case you can specify a different 32-bit pattern and it will just simply change pixels on or off depending on those bits so I want these to be dashed lines so I can do that by specifying this as the pattern which says for pixel should be on 4 pixel should be off 4 on 4 off 4 on 4 off etc etc in this case by clamping the X the coordinate to zero I've extracted the information for the y-axis and I can do something similar to extract the information for the x-axis let's take a quick look so though we can see we've got the axes going through the middle of the screen that's good that's my zero zero location and I'm going to hold down the middle mouse button and move the mouse around and the world is panning you might not be able to see the faint blue dots on the YouTube video but they are there switch it over to full screen as shown in the panning and zooming video zooming is a little bit more complicated the principle is that we look at where the mouse is before the zoom look at where it is after the zoom and then translate the screen by that difference and that allows you to zoom in under the mouse cursor ie the pixel that is under the mouse cursor will remain under the mouse cursor so that gives you a very intuitive to use zoom so here I've took my mouse coordinates and worked out where my mouse is in the world I'm now going to respond to user zoom commands and I'll do this in two ways either they can hold the cue button down or they can scroll the mouse wheel and this is a new function - in this case we're zooming in we want to scale things up so we change our scale value by making it larger on the other hand if the user presses the a key or Scrolls the mouse wheel backwards they'll zoom out and the reason I've included the keys as well is if you're watching this on a laptop and you don't have a scroll button you won't be able to zoom in and out very easily once the scale value has been changed we need to now calculate where the mouse is again in world space and then translate the world by the difference between the two mouse positions let's take a quick look so I'm panning and I'm changing my mouse wheel and you can't maybe see it very clearly if the blue dots aren't showing up what we are certainly zooming in and we zoom in relative to where the mouse cursor is on the screen very nice I'm going to add an additional variable now another vector floating-point type called V cursor and that's going to represent where the mouse is in the world but why is it different to the regular mouse cursor well in order to draw things accurately and cleanly it helps if the cursor can snap to a particular location so in this case I want the mouse cursor to snap to the nearest unit value or our grid spacing in world space and this is a very simple calculation to do this means that the user can't select anything in between the grid values since we now have a slappable cursor I'm actually going to draw that on the screen by drawing a small circle around the snapped location and I'm also going to display its coordinate via text using the draw string function so let's take a look so we can see a little yellow circle representing the nearest grid point that the cursor is snapped to in fact if i zoom in quite a bit you can see it doesn't move around continuously like the mouse cursor does it snaps to the nearest location and panning and zooming works just fine too so that's very nice it might even be worth wrapping up panning and zooming into some sort of reusable container I can use in future videos and applications but I'm not going to do that today so let's get on with programming our class structure we know that for this simple demonstration I'm going to need a structure that represents a node and a structure that represents a shape now our shapes are going to contain nodes and our nodes contain pointers to shapes so I've got a bit of a circular reference I can solve that quite quickly by for declaring my shape above the node our shape contains a vector of nodes but because I've planned ahead and you need to do that when working with polymorphism and object-oriented programs I know that I want to specify what the maximum number of nodes is a particular derived shape can have for most of the shapes it's - a line has a start and an end a box has a top left and a bottom right a circle has a midpoint and a point on the circumference my shapes also going to have a color and we'll start them off by them being green my shapes are going to be responsible for drawing themselves so I'm adding a virtual function in this case and it's a pure virtual function I've put the equals zero at the end and so this is indicating to the compiler that derived classes from s shape must provide an implementation of the draw yourself function and in this case it takes a pointer to the pixel game engine because I've defined s shape outside of the pixel game engine I pass a pointer of it into the draw yourself function so it can access all of the familiar drawing tools we have available the user-defined shapes by placing nodes and these nodes belong to the shape that's currently being drawn so I'm going to make it the case that the shape is responsible for creating the node and giving it to the rest of the application to handle appropriately this is going to be the same for all shapes so I don't need to make this method virtual it's called get next node and it takes in a position in world space creates the node if it can and returns a pointer to that node the number of nodes of shape can have is governed by the n max nodes variable so if we've already reached that value then we'll just return null pointer we can't create anymore nodes the shape is complete for example you can't have three nodes on a line you can only have two else if there is room for more nodes then I'm going to create a new instance of a node and add it to my vector of nodes and now you'll notice something truly horrific something I've done a video about telling you not to do I'm returning a pointer to the location of an element in a vector very very very very bad however what we'll see in a minute is we can do this quite legitimately providing were quite careful on how we set up the vector in the first place now all of our shapes are responsible for drawing themselves and they don't have access to the world to screen transform information but since this information is going to be the same at all times for all shapes I'm going to create two static variables to this structure called world scale and world offset and I'm also going to provide a local implementation of the world to screen transform so the shape can actually do this transform for itself it doesn't need the screen to world one that doesn't make any sense the shape only exists within world space we know that our shapes are going to have derived classes that override the draw yourself function to distinguish themselves from each other circles are not drawn the same as lines for example however all of these shapes are responsible drawing their own nodes and this doesn't change / shape so we may as well also include in our base structure the facility to draw the nodes of the shape and this works in a very similar way we'll pass a pointer to the pixel game engine into a draw nodes function iterate through the vector of nodes take the nodes location and transform it from world space to screen space and then draw a little red circle at that location we mustn't forget whilst I'm at the bottom of the structure that we've added to static members to this structure so we must initialize them and I just want to demonstrate that our s-shaped structure is abstract by trying to create an object of it directly you see it doesn't like it and it says objects of abstract class type s shape is not allowed and it goes ahead to tell us that the draw yourself function is a pure virtual function ie it can't find any implementation for it so we've protected ourselves from writing code that functionally wouldn't work I appreciate that this video moves a lot quicker than most of my others but now we've got this set up we can start to see some of the benefits of thinking in terms of objects and polymorphism so let's create the simple line structure my line structure inherits from my base shape structure and I'm going to give it a constructor and in this constructor we set the maximum number of nodes this shape can have two to the like and have a start and an end now remember before where we did something which was an example of absolutely horrific practice we returned a pointer to the element of a vector well that's bad because vectors can move the contents around without you knowing so the pointer can become invalid however we know how big that vector is going to be for a line there's only ever going to be two nodes so I'm going to tell that vector go and reserve two nodes worth of space please this means the vector won't be reorganized beyond our control it's the same as declaring an array in this instance and because the draw your self function was abstract we must provide an implementation for it in this derived class and we can signify to our compiler that actually look hello width we want to over destroy yourself function this keyword is optional but I think it gives you a nice little visible tic to say you are overriding a virtual function in a base class drawing a line is quite simple we want to take the coordinates of the two nodes that we have in world space and convert them to screen space and simply draw that line I'll now add to our application class a pointer to a line once we've handled all the panning and zooming and snapping we can start handling the remainder of the user interface through a line I only want to create one if the user presses the L key this signifies that we're going to create a new line I'm also going to add a pointer to unload I'll call that selected node so at any given point whatever node is pointed to by selected node is movable by the mouse cursor I'll default that to null pointer I'm going to assume that the user pressed the L key at the starting point of the line so I'm going to set my selected node variable to whatever is returned from the get next node function of the line shape which if you remember turns the current location passed to that function as a node since that's the first node placed I don't really want to move that around with the mouse straight away so I immediately want to get the second node because that is the one I'm going to move with the mouse as I move the mouse around any node pointed to by the selected node pointer I'm going to set its position to my snap to cursor location as I click with the mouse I want to continue placing nodes until the shape tells me there are no nodes left to place if the shape returns null pointer when the get next node function is called then the shape is complete I there are no more nodes available to define it if the shape is complete I'm going to set its color to white once I've drawn my dots and my axes I want to draw my line so I'm going to call the draw yourself function and the draw nodes function and pass in at this reference which is the pixel game engine into those structures so they can draw themselves but I don't want to do this if my line is equal to null pointer before we can draw any shapes however we need to set the static variables in our base shape class to set the scale and offsets for the world to screen translation let's take a look I'll zoom in a little bit I'm pressing the L key which has placed the first node and it's also placed the second node but the second node is now attached to the mouse cursor and the first and second nodes are used by the line shape to determine the start and end of the line so we can see it's green and it currently follows the mouse cursor around until I click and we've defined the line shape we've now almost finished a skeleton application we can pan and zoom and we have the facility to add a simple shape in this case a line but I think for our application to be useful we want to add multiple shapes or at least multiple lines so I'm going to create a list to store our line shapes in changing our application to hold multiple lines is actually quite simple I'm going to use a standard list to do this and create a new list called list of shapes I'm also going to create a temporary variable called temp shape which is going to represent the line that we're currently trying to draw on the screen so once the line has been confirmed it gets added to the list of shapes whereas before we created a new line directly now we're creating a temporary shape we can determine what the mouse behavior implies by knowing if temp shape is set to null pointer or not so if temp is not equal to null pointer then we're currently trying to draw a shape we're not just moving the mouse around on the screen so if we're trying to draw a shape then as before we see if there are only nodes available left for the shape if there are no nodes left then the shape is complete so it's no longer temporary in fact we want to push it to our list of shapes we also want to change the drawing code for our temporary shape now the temporary shape is the instance currently being drawn we also have a list full of shapes that also need drawing so we'll do that before we draw the temporary shape by iterating with a little Auto for loop through our list of shapes let's take a look so I'll press the L button we draw a line and click and press the L button we draw a line and click perfect lots and lots of lines I feel it's also very useful to be able to move the nodes once they've been placed so we need to put a routine into our s-shaped structure to tell us if we've hit any of the nodes contained within that shape and this is a very simple addition this function hit node takes in a location in world space it then iterates through all of the nodes for this particular shape and works out the distance between the nodes position and the position we've passed in if that distance is less than 0.01 we don't want to do a direct comparison because we're working with floating-point numbers it would very rarely return true so it's better if we look at what the magnitude of the distance is between those two points if it's close enough we'll return the address of the node that's been hit and we'll set our selected node pointer to the address of the node this function returns if no nodes are hit then we'll return a null pointer I'm going to response to the M key being pressed to signify I want to move the node that is under the cursor firstly I'll set the selected node to null and then for all of the shapes that I've currently placed I'm going to iterate through them and call the hit node function on my cursor location if any of these return something that isn't null pointer then I'm going to set that to my selected node pointer and break I found a node and I've now set it to something I can control with the mouse let's just quickly try this out so I'll draw a line and I'll draw another line I'll put my cursor over the beginning of that first line and press the M key and you can see I've now got a pointer to that node and I can manipulate that node with the mouse to try the other end of that line very nice so if I make a mistake whilst I'm drawing my lines out I can go back and fix it our list of lines is all very good I can draw and manipulate unique lines on our canvas I want to add more shapes now so I could create additional lists to contain all of those shapes and at runtime try and sort it all out by checking what type is each object but I'm not going to do that instead I'm going to now exploit polymorphism and so yes it's been a little while coming with a bit of complicated code so far but let's get to it let's turn this now into a polymorphic application here we're restricted to objects that have a type line but as we've been learning we can use polymorphism so I can actually set this to shape and I'll do the same for our temporary shape now what we'll look at is where we press the L key to create a new line we know that temp shape is of type shape but we're tributing to it a new object of type line and the compiler is completely fine with this if you don't believe me a quick check it's working just fine so we have a list set up to store a type of one object shape but we're quite happily shoving into that list lines and in fact as long as we adhere to the interface defined by shape ie we provide something which implements this draw your self function we can add all sorts of objects to our list of shapes in fact let's do just that let's add the box shape so I'm going to start by just cutting and pasting the line shape I'll change it to s box need to change the constructor just as before a box is going to be defined by two nodes I don't want all of these comments again so we'll reserve that in our vector of nodes in the draw yourself function instead of drawing a line I'm going to draw a rectangle where I pass in the top left coordinate and the width and the height and that's an important distinction to make here it's not the bottom right corners it's the width and the height so you need to calculate that based on the transformed world coordinates so I've created a very simple derived structure from shape called box here was the code where we responded to the L key being pressed to add a line I'm going to copy and paste that and instead of the L key I'm going to make it the B key for box but this time instead of adding a new line we want to add a new box and everything else can stay the same our selected node stays the same I'll manipulating the nodes say the same our ending of the shape stays exactly the same and our drawing of the shape stays exactly the same let's take a look so as before we've got lines now if I press the B key it draws a box we've added some quite different functionality to the application without changing very much of it and that change in functionality has been entirely encapsulated within the box structure perfect we now have lines and boxes and these are unique shapes unique objects that contain their own drawing code they've become encapsulated and self-contained the nice thing about this is our application hasn't had to do any filtering of how to handle these shapes they simply draw themselves our application sees them as nothing more than just a shape and this is really the power of polymorphism so let's add some more shapes we've now got a very powerful pattern to which we can start adding all sorts of unique functionality let's add a circle again a maximum number of nodes of two it's going to be the midpoint of the circle and a point on the circumference and we'll fill in the draw yourself function firstly I can get the radius of the circle by just being the distance between the two points and I'm going to draw a dashed line between those two points to represent that radius and then I want to draw the circle itself but don't forget we need to scale the radius by our world scale coefficient here is our code for adding a line here is our code for adding a box we'll just add in exactly the same code but this time we'll create a type circle let's take a look line box circle and don't forget we can pick up the points and move them around and we can have lots of shapes this one here is a very very small circle there we go hopefully you can see this is a very powerful pattern now so I'm going to add something a bit more sophisticated this time it's going to be a spline I'll call it curve and it's going to take in three nodes because this simple curve type has an end point a start point and a point in the middle where the curve moves towards I've done an entire video series just about splines so please check that out we know that when the user first tries to create the spline it'll have placed a node and immediately also issued a second node which they can drag around so if we've got less than three nodes we're drawing the first line from the starting point to the middle point if we have got three nodes we've got enough information to draw both the structural lines of the spline but also the curve itself so I'm drawing those structural lines as dashes but I'm also going to then iterate with a small step along the curve and draw it out to the screen in fact in this code I'm breaking the curve into lots of little line segments and drawing those so the curve shape is a little bit unique it requires more information in order to place it also draws itself differently depending on how much information that it's got but this difference in functionality is entirely capsulated within the curve shape we don't need to change any of our application in order to facilitate adding curves so I'll responds to the s key in this instance to add a curve spline let's take a look press the S key so we've only got two nodes on the screen so far so it's a structural line I click it then allocates the second node and starts to draw the curve and click again to complete it and so there you have it a simple demonstration of using polymorphism to add features to an application without changing the underlying nature of that application a very powerful tool but as with all things object-oriented programming we really need to think about it in advance it's no good just jumping in at the deep end and writing lots of code and hoping it's all going to come together that's called spaghetti code and it will be early maintainable and probably won't work and you'll end up doing several rewrites so I really recommend sitting down and thinking about your application before developing it anyway all of the code for this video is available on github please download it and have a make some modifications add some new shapes even if you've enjoyed this video a big thumbs up please have a think about subscribing come and have a chat on the discord and hopefully I'll be back in my normal programming place next time take care
Info
Channel: javidx9
Views: 94,190
Rating: 4.9757504 out of 5
Keywords: one lone coder, onelonecoder, learning, programming, tutorial, c++, beginner, olcconsolegameengine, command prompt, ascii, game, game engine, polymorphism, object oriented programming, oop, virtual, inheritance, computer aided design, pixel game engine, olcPixelGameEngine
Id: kxKKHKSMGIg
Channel Id: undefined
Length: 41min 43sec (2503 seconds)
Published: Fri Mar 08 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.