Perhapsanothersolutionistocreateonetypeofobject, whichisalloftheobjectsandtheobjectitselfinselfdeterminedwhattodoin a givenscenario.
Approacheslikethisarevalid, buttheycanbe a bitmessyonwemayaswellusethetools C++ providesforustodothisondhetheprimarytoolandwhatthisvideois, thatis.
Polymorphismwillengineerourcodeinsuch a waythatthecompilercandecideatruntimewhichmethodstocall, whatshapestodrawandhowthingsshouldlook.
Now I willstartbysayingthatPolymorphismisnot a beginnertopic, althoughtheway I'm goingtoshowitinthisvideo, we'rereallyonlygoingtostartlookingatitthatthemosttoplevel, objectorientedprogrammingandpolymorphismis a reallyrichanddetailedtopicinitsownright.
Butyoucanachievequitepowerfulthingsjustbyknowingtheverybasicsforthisvideo, I'm goingtoassumeyoudoknow a littlebitaboutclassesalreadyonthelowPolymorphismdoesexistinlotsofdifferentlanguages.
I'm goingtobespecificallylookingat C plusplus.
Let's stopwith a simpleclassinthiscasecalled A and A has a functioncalledDoSomething.
What's theDo?
SomethingFunctiondoesdependsentirelyonwhatClass A is.
Now I'm goingtoassumethatwehave a setofstructuresinourprogramthat's allquitesimilarinnature.
I theyhave a lotofcommonalitybetweenthem, so I'm goingtotryandpackagethatcommonalityupinclass A toturnitinto a baseclass.
Inthisinstance, Class B Class B inheritsallofthemethodsandattributesfromclass A, assumingthatitcandotowhateveraccessspecifieswe'vedeterminedareonthosepropertiesoffclass A.
If I createanobjectoftype B andcallthedosomethingfunction, thenthatdosomethingfunctionisdefinedbythebaseclass, eh?
I can, ofcourse, overridethedosomethingfunctionbysimplyredefiningitinclass B.
Now, if I createanobjectoftype B andcallthedosomethingfunction, itwillcallthisoneinstead.
Anditgoeswithoutsayingthatif I createanobjectoftype A andcalltodosomethingfunction, itwillcallthisone.
Perhaps I haveanotherderivedclass.
Class C.
Well, exactlythesamethingapplies.
Thistoo, couldhaveitsowndosomethingfunction.
Sofar, sogood.
Nothingoutoftheordinary.
Butwestartedthiswith a particularcaveatonWesaidthattheseclassesthatderivefromClass A wereinsomewaysimilaronwecreatedClass A as a baseclasstoencapsulatethecommonfunctionalitybetweenthetwodivideclassesoninapplications.
It's usefultogroupthingsthataresimilartogether.
Andsohowcanwedothisif I createanobjectoftypeClass?
A.
Itisveryclearlydefined, wasbigoftype A.
Likewise, if I createanobjectofType B, itisveryclearlydefinedasbeinganobjectoftightbe.
Itisnotanobjectoftype A, eventhoughbeinheritsfrom a itisdefinedasbeingbenaturally.
ThesamealsoappliestoanobjectofType C.
Whenwewanttogroupthingsthat a similarin C++, wehaveseveralwaysofdoingthis.
Oneapproachis, ofcourse, touseanarray.
Butwheneverwespecifyanarray, alloftheelementsofthearrayofthesametype, perhapswecoulduse a vector.
Theconvenientthingtodoistohinttothecompilerthat B and C areinfactderivedfrom a onthatourvector.
Honoreonlystoreselementsofftype A.
Well, thisisquitenice, andwe'realmostthere.
Butif I wantedtouse a specificelementofourvectorofType A andcallourdosomethingfunctionaswesawbefore, it's goingtocallthedosomethingfunctiondefinedbyClass A.
Instead, I'm goingtodosomethingthatappears a littlestrange.
I'm goingtocreateanobjectoftypeClass A.
But I'm notjustgoingtocreateanobject.
I'm goingtocreate a pointertotheobject.
Sothismeansnowwhen I'm creating a newobject, I needtousethenewkeywordorsmartpointtoequivalent.
Butnow I candosomething a bitspecialbecause B and C werederivedfrom a onAll I'm storingis a pointertowhere a mightresideinmemory.
I canactuallycreate a newobject B andofcourse I candoexactlythesameformyClass C type.
Sonowwhen I createmyvectortoe, holdmysimilarobjectstogether, I'llmakeitholdsomepointerstoClass A andthrewsomesmokeandmirrorsimplementedbythe C++ compiler.
Whatweareimplyinghereisthatifclasses B or C override a methodinclass A, thenifweweretocallsuch a methodinthiscase, ourdosomethingmethodthatitwillcalltheappropriatemethodrelatedtotheclassthatwasconstructed.
Andthat's quite a complexandpowerfulthing.
I cannowstorein a singlecontainer, a groupofsimilarobjectsthatallhaveuniquefunctionalitybut a commoninterfaceineffect, wehaveallowedthebaseclass A tomorphintomultiplesubclassis a polymorphism.
Ifhoursbefore, wejustdirectlycalledthedosomethingmethodontheobjectstoredinourvector, regardlessofwhetherthatobjectwasoftype B or C, itwouldstillcallthedosomethingmethodrelatedtoclass A.
Weneedtotellthecompilerthatdosomethingis a candidatetobeoverwrittenby a baseclasson.
Wecandothatwiththevirtualkeyword.
Thishintstothecompilerthat I maybeoverwrittenif I'm notoverriddenthananycalltothedosomethingfunctionwillnaturallybeimplementedbythebaseclass, eh?
SoifanybodynowtriestocreateaninstanceofType A, itwillfailandthrowanerrortotheprogrammerbecausenoimplementationofthisfunctionexists, eventhoughsomethingpotentiallycancallit.
Andsothisis a verypowerfulandusefulwayoffwrappingupyourprogramstructure.
Now I appreciatetosomeofyouthismayallseemincrediblyalien, butdon't worry.
I thinktheexamplecodethat's comingupreallyshowsthepowerofthisin a niceway.
Solet's brieflytake a lookattheclassstructureforthecatprogram.
I demonstratedatthestart.
I have a basestructurecalled s shapeandfromthatbasicstructure, I deriveuniqueclassesthatrepresentstheshapesthat I have.
So a line, a box, a circleon a curve.
Allofthesethingsareindeedshapes, soit's veryusefultorecognizethemas a singularshape.
Buttheylookdifferently.
So I wanteachoftheseclasseslined, boxcirclingcurvetoberesponsiblefordrawingitself.
Sotheywillallhave a methoddrawwhichdrawsittothescreen.
Soitseemsthatdrawis a greatmethodtobephoneintothebaseclass.
Naturally, I'm goingtostartbyusing a skeletonOLCpixelgameengineprogram.
Andifyou'venotheardofthepixelgameengine, it's a verysimpletechnologythat I'vecreatedthatallowsyoutodrawthingstothescreenquitequicklyandsimply.
And I'm goingtoconstruct a pixelgameenginequite a highdefinition.
Oneunusually.
Thiscaseisgoingtobe 1600 pixelsby 960 pixels, andthere's goingtobe a 1 to 1 relationshipbetweenpixelgame, enginepixelsandscreenpixels.
I havemytraditionalonusercreateanunusedupdatefunctionsonrightnow.
Allonusurpeditdoesisgrabthemousecoordinatesonthescreenandstoresthemas a floating 10.2 d vectoryousawinthepreviewatthestartofthevideothatwecanpanandzoomaroundthescreenon.
I'vealreadygot a video.
It's justaboutthistopic, so I'm notgoingtogointoverymuchdetailhere.
I'vealsoadded a coupleofotherfeaturestothepixelgameengine, includingtheabilitytodrawdashedlineswhichwillwillsee a littlelaterononthatlonglastmousewheelsupport.
Sothefirstfunctionalatdirectlycopiedfromthepanningandzoomingvideoandmodifiedtosuitthenewfloatingpointvectortypeisworldtoscreenthattakesin a vectorinworldspaceandgivesmetoscreencoordinatesasanoutput.
Once I'vegotthemousecord, it I'm goingtoenablezoomingbyscrollingthewheelbutpanningbyholdingdownthemousewheelandmovingthemouseso I wanttobesensitivetothemousewheelbeingpressed, andthat's goingtostorethestartpanlocation.
As I havethebuttonhelddownandmoveitaround.
I wanttoupdatemyoffset.
Solet's seequicklyaboutdrawingtheworldfirst.
I'm goingtoclearthescreenonbecause I canseeintothefuture, and I'm goingtoneedsometemporaryinterviewcoordinatestorepresentlocationsinscreenspace.
Weonlywanttodrawwhatwecanseetraditionally, so I wanttoworkoutwhatthevisibleextentsoftheworldareontodothisverysimple.
I simplyuseourscreentoeworldfunctionwiththetopleftcornerofthescreenonthebottomrightcornerofthescreen, andthiswillgivemethedimensionsofthevisibleworldinworldspace.
I wantthattobe a littlebitofoverlaparoundtheedgeofthescreen, justsowhenwe'redrawinglines, youdon't seethemclipping, so I'm flooringtheleftandtopvalueson.
I'm takingtheceilingvalue a roundingupthebottomandrightvaluesbecause I knowtheextentofmyvisibleworld.
I cansimplyhavetwonestedfourloopsnowthatiteratedalongeachaccesssteppinginmygridsizebecausenowwe'reiteratingthroughworldspace.
Mygradewasjustsettoeone, but I'llusetheworldtoscreenfunctiontochangethisworldspacequartersintothescreenspacecoordinatesandusethatlocationtoplot a pixelsafeintheknowledgethatitdoesn't matterwhere I amintheworld, I'm onlydrawingwhatthelittlewindowofthescreencanseeintothatworld.
I alsowanttodrawsomeaxesintotheworldso I canseewheremy 00 locationis.
And I'lldothisMike, extracting a linefromworldspacebaseduponthevisibleextentsoftheworldon, I'llcapturethoseinscreenspaceintheSX S Y E X and E Y variables, andit's simply a caseofdrawing a linebetweenthosetwocoordinateson.
I'm goingtodrawitingray, but I'm goingtojustquicklyandverysneakilyshowyou a newfeaturethat I'veaddedtothepixelgameengine, whichallowsyoutodrawlineswithpatternsonInthiscase, youcanspecify a different 32 bitpattern, anditwilljustsimplychangepixelsonoroff, dependingonthosebits.
So I wantthesetobedashedlinesso I candothatbyspecifyingthisasthepattern, whichsaysFourpixelshouldbeonfourpixel, shouldbeofffouronfouroff, fouronfouroffetcetera, etcetera.
Inthiscase, byclampingtheexrecorded 20 I'veextractedtheinformationforthe Y axis, and I coulddosomethingsimilartoextracttheinformationforthe X axis.
Let's take a quicklooksothatwecanseewe'vegottheaxesgoingthroughthemiddleofthescreen.
That's good.
That's my 00 location, and I'm gonnaholddownthemiddlemousebuttonon.
Itmightevenbeworthwrappingup, panningandzoomingintosomesortofreusablecontainer I canuseinfuturevideosandapplications.
But I'm notgoingtodothattoday, Solet's getonwithprogrammingourclassstructure.
Weknowthatforthissimpledemonstration, I'm goingtoneed a structurethatrepresents a nodeon a structurethatrepresents a shape.
Nowourshapesaregoingtocontainnodesandunknownscontainedpointerstoshapes, so I got a bitof a circularreference.
I cansolvethatquitequicklybyForddeclaringmyshapeabovethenoteareshaped, contains a vectorofnotes.
Butbecause I'veplannedahead, thenyouneedtodothatwhenworkingwithpolymorphismonobjectpointedprograms I knowthat I wanttospecifywhatthemaximumnumberofnodesis.
A particularderiveshapecanhaveformostoftheshapes, it's to a linehas a startinganend.
A boxhas a topleftonthebottom, right?
A circlehas a midpointon a pointonthecircumference.
Myshapesalsogoingtohave a color, andwe'llstartthemoffbythembeinggreen.
So I'm adding a virtualfunctioninthiscase, andit's a purevirtualfunction.
I'veputtheequalzeroattheend.
Andsothisisindicatingtothecompilerthatderivedclassesfrom s shapemustprovideanimplementationofthedrawyourselffunction.
Andinthiscase, ittakes a pointertothepixelgameenginebecause I'vedefinedtheirshapeoutsideofthepixelgameengine, I pass a pointerofitintothedrawyourselffunctionsoitcanaccessallofthefamiliardrawingtoolswehaveavailable.
Theuserdefinedshapesbyplacingnodesonthesenodes, belongtotheshapethat's currentlybeingdrawn, so I'm goingtomakeitthecasethattheshapeisresponsibleforcreatingthenodeongivingittotherestoftheapplicationtoehandle.
Appropriately, thisisgoingtobethesameforallshapes, so I don't needtomakethismethodvirtual.
It's calledGetNextNode, andittakesin a positioninworldspace, createsthenoteifitcan, andreturns a pointer.
Forexample, however, alloftheseshapesareresponsiblefordrawingtheirownnodes, andthisdoesn't changepershape, sowemayaswellalsoincludeinourbasestructurethefacilitytodrawthenodesoftheshape, andthisworksin a verysimilarwaywillpass a pointertothepixelgameengineinto a drawernodesfunction.
It's a rightthroughthevectorofnodes.
Takethenodeslocationandtransformitfromworldspacetoscreenspaceandthendraw a littleredcircleatthatlocation.
I appreciatethatthisvideomoves a lotquickerthanmostofmyothers, butnowwe'vegotthissetup.
Wecanstarttoseesomeofthebenefitsofthinkingintermsofobjectsandpolymorphism, solet's createthesimplelinestructuremylinestructureinheritsfrommybaseshakestructure, and I'm goingtogiveit a constructorandinthisconstructor, wesetthemaximumnumberofnodes.
ThisshapecanhavetwototheLycan.
Have a startinanend.
Now, remember, beforewedidsomethingwhichwasanexampleofabsolutelyhorrificpractice, wereturned a pointertotheelementofthevector.
Onceyou'vehandledallthepoundingandzoomingandsnapping, wecouldstarthandlingtheremainderoftheuserinterfacefor a lineonlywanttocreateoneiftheuserpressestheElke.
So I'm goingtosetmyselectednodevariabletowhateverisreturnedfromthegetnextnodefunctionofthelineshape, which, ifyouremember, turnsthecurrentlocationpassedtothatfunctionas a note.
Sincethat's thefirstnoteplaced, I don't reallywanttomovethataroundwiththemouthstraightaway, so I immediatelywanttogetthesecondnodebecausethatistheone I'm goingtomovewiththemouseAs I movethemousearound.
Butthesecondnoteisnowattachedtothemousecursor, andthefirstandsecondnodesareusedbythelineshapetodeterminethestartandendofthelinesowecanseeit's greenanditcurrentlyfollowsthemousecursorarounduntil I clickandwehavedefinedthelineshape.
I'm goingtorespondtothe M keybeingpressedtosignify.
I wanttomovethenodethatisunderthecursor.
Firstly, I'llsettheselectednodetoknow.
Andthenforalloftheshapesthat I'vecurrentlyplaced, I'm goingtoreiteratethroughthemandcallthehitnodefunctiononmycurse, a location.
Ifanyofthesereturnsomethingthatisn't nopointer, then I'm goingtosetthattomyselectednotepointeronbreak.
I found a noteonDive.
Nowsetittosomething I cancontrolwiththemouse.
Let's justquicklytrythisoutso I'lldraw a lineand I'lldrawanotherline.
I'llputmycursoroverthebeginningofthatfirstlineandpressedthe M key, andyoucansee I'venowgotappointedtothatnode, and I canmanipulatethatnotewiththemousetotrytheotherendofthatline.
Verynice.
Soif I make a mistakewhilst I'm drawingmylinesout, I couldgobackandfixit.
Ourlistoflinesisallverygood.
Aikendrawermanipulateuniquelinesonourcanvas.
I wanttoaddmoreshapesnowso I couldcreateadditionalliststocontainallofthoseshapesand a runtimetryandsortitalloutbychecking.
Whattypeiseachobject, But I'm notgoingtodothat, said I'm goingtoknowexploitpolymorphism.
Andso, yes, it's been a littlewhilecomingwith a bitofcomplicatedcodesofar.
Butlet's gettoit.
Let's turnthisnowinto a polymorphicapplicationherewererestrictedtoobjectsthathavetypeline.
Butaswe'vebeenlearning, wecanusepolymorphism, so I canactuallysentthistoshape.
And I'lldothesameforourtemporaryshape.
NowwhatwilllookatiswherewepresstheElketocreate a newline.
So I'm goingtostartbyjustcuttingandpastingthelineshape.
I'llchangeitto s box.
I needtochangetheconstructorJustusbeforetheboxisgoingtobedefinedbytwonodes.
I don't wantallofthesecommentsagain, sowe'llreservethatinourvectorofnotesinthedraweryourselffunction.
Insteadofdrawing a line, I'm goingtodraw a rectanglewherepassingthetopleftcoordinatesonthewidthandtheheight, andthat's animportantdistinctiontomakehere.