Upload
russell-mccormick
View
49
Download
0
Embed Size (px)
DESCRIPTION
hi
Citation preview
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 1/10
Lab9:C++classesclassesandobjects,constructorsanddestructors,refactoring
Goals
Afterthislabyouwillbeableto
1. Useclassesinplaceofstructs.2. Writeconstructorsanddestructorsforclasses.3. Usetwodimensionalarrays.4. Refactorcode.
Apartfromteachingyoutouseclassesand2darrays,thislabisdesignedtohaveyouworkrepeatedlyonthesamecode.Bynowyoushouldbereadingandwritingcodemuchmorequicklythanatthebeginningoftheclass.Youshouldalsousingyourtexteditormoreexpertly,forexampleusingsearchandreplace,movingaroundquicklyinthefile,cuttingandpastinglinesusingkeystrokes,etc.Youwillspendmanyhoursinyourtexteditorduringyourdegreeandbeyond:youshouldmasterit.
Refactoringcode(Task3)isanactivitythatexercisesyoureditorkungfu,andwillnottaketoolongifyouusetheeditorwell.
Setup
Notethattheseinstructionsnolongerincludeallsteps.Youshouldknowhowtodothesethingsbynow.Ifindoubt,refertopreviouslabinstructions.
Intheterminal:
1. Addthenewdirectory'9'totherootdirectoryofyourrepository.Thiswillbetheworkingdirectoryforalltheinstructionsbelow.
2. FetchthenewmaterialforLab9,storedinacompressedtarball:
$wgethttp://www.cs.sfu.ca/~vaughan/lab9.tgz
3. Expandthearchiveintotheworkingdirectory:
$tarxzvflab9.tgz
IntroducingC++C++extendstheClanguagewithsupportforclassestosupportObjectOrientedProgramming,andtemplatestosupportGenericProgramming.Thisweekwewilllookatclasses,butfirstasummaryoftheworkflowchangesyouneedtouseC++.
1. C++sourcecodefileshavetheconventionalsuffix".cpp"or".cc",insteadofC's".c".2. C++headerfilesmayhavethesuffix".hpp"or".hh",orstickwithC's".h".Wewilluse
".hpp"tomakeitclearwhenwehaveaC++header.3. TheGNUC++compilerprogramiscalled"g++",insteadof"gcc".
Notethattheintructionsbelowdonotprovidecompilecommandsforyoutocut'n'paste.Youwillneedtoreadthenotesaboveandconstructyourowncompilecommands.
AC++primerforCprogrammers
HereisaverygoodandconciseintroductiontoC++forCprogrammers.byProf.TomAndersonoftheUniversityofWashington.
Prof.AndersonhasstrongopinionsabouttheusefulandlessusefulpartsofC++,anddrawsyourattentiontothemostimportantpartsinlessthan12pages.Thedocumentisdatedinsomeways,butmostoftheadviceisexcellent.
Thingstodo:
1. ReadSections1through3carefully:theywillhelpwithyourTasksthisweek.
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 2/10
2. ReadSections4and5atyourleisure,andrememberthatopinionsvarywildlyonthissubject,andthingschangeovertime.
3. NotethattheStandardTemplateLibrary(STL)isnowmatureandsupportedbymostcompilers,andyoucanandshoulduseitwithconfidence.WewillshowyouthebasicsoftheSTLinalaterlab.
Notethatyoureallyareexpectedtoreadthedocument,andthefollowinginstructionsmaynotbeenoughbythemselvestohelpyousolvethetasks.Anothergoalofthislab(andtheclass)istoencourageyoutoreadaroundyoursubjectsandfeelpersonalresponsibilityforlearning.
**STOP**READTHEPRIMERDOCUMENTBEFORECONTINUING**
Task1:ImageclassWewilldevelopaC++program,usingideasfamiliarfrompreviouslabsplusnewsyntaxforcreatingclasses.
Requirements
1. ReadtheGuidesectiononclasses,constructorsanddestructorsbelow.2. WriteanewC++sourcefile"image.cpp"thatcontainsacompleteimplementationofthe
ImageclassdeclaredintheprovidedC++headerfile"image.hpp".3. Yourfilemustinclude"image.hpp"withoutanymodifications.4. Writeyourownmain()functionfortestingyourclass,butputitinanothersourcefile:do
notdefinemain()in"image.cpp"asthiswillinterferewiththeservertest.
Submission
Addandcommitthesinglefile"image.cpp"toyourrepo.
Guide
CtoC++
HereisaninterfacedefinitionforanimagedatatypeinC,extendedfromtheonewedevelopedinanearlierlab:
typedefstructimage{unsignedintcols;unsignedintrows;uint8_t*pixels;}img_t;
/*Returnsanimg_tstructurecontaining0x0pixels.*/img_timg_create(void);
/*Freesallmemoryallocatedforimg*/voidimg_destroy(img_t*img);
/*Changesthesizeofanimage,allocatingmemoryasnecessary,andsettingallpixelstofillcolor.Returns0onsuccess,oranonzeroerrorcode.*/intimg_resize(img_t*img,unsignedintwidth,unsignedintheight,uint8_tfillcolor);
/*Setsthecolorofthepixelat(x,y)tocolor.Returns0onsuccess,elseanonzeroerrorcode.If(x,y)isnotavalidpixel,thecallfailsandtheimagedoesnotchange.*/intimg_set_pixel(img_t*img,unsignedintx,unsignedinty,uint8_tcolor);
/*Getsthecolorofthepixelat(x,y)andstoresattheaddresspointedtobypcolor.Returns0onsuccess,elseanonzeroerrorcode.*/intimg_get_pixel(img_t*img,unsignedintx,unsignedinty,uint8_t*pcolor);
WecouldusethesedefinitionsasisinaC++program,sinceCisalmostasubsetofC++.However,animplementationinC++stylewouldhavethefollowingdifferences:
1. Thestructurewouldbeaclass
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 3/10
2. Thefunctionsoperatingonimagestructureswouldbemethodsoftheimageclass,andwouldnotneedthe"img_"prefix.
3. Imageclassmethodsdononeedapointertotheimagedatastructure,sincetheyautomaticallyhaveathispointertotheobjectonwhichthemethodwascalled.
4. Thefieldsofthestructwouldnotbeaccessiblefromoutsidetheclass:animagecouldonlybemodfifiedusingitsmethods.
5. img_create()wouldbeaconstructor6. img_destroy()wouldbeadestructor
HereistheC++version:
classImage{
private:unsignedintcols;unsignedintrows;uint8_t*pixels;
public:/*Constructsanimageof0x0pixels.*/Image();
/*Freesallmemoryallocatedforimg*/~Image();
/*Changesthesizeofanimage,allocatingmemoryasnecessary,andsettingallpixelstofillcolor.Returns0onsuccess,oranonzeroerrorcode.*/intresize(unsignedintwidth,unsignedintheight,uint8_tfillcolor);
/*Setsthecolorofthepixelat(x,y)tocolor.Returns0onsuccess,elseanonzeroerrorcode.If(x,y)isnotavalidpixel,thecallfailsandtheimagedoesnotchange.*/intset_pixel(unsignedintx,unsignedinty,uint8_tcolor);
/*Getsthecolorofthepixelat(x,y)andstoresattheaddresspointedtobycolorp.Returns0onsuccess,elseanonzeroerrorcode.*/intget_pixel(unsignedintx,unsignedinty,uint8_t*colorp);};
Heretheyareagainwithoutthecommentssothefunctionalpartsareeasiertocompare:
C:
typedefstructimage{unsignedintcols;unsignedintrows;uint8_t*pixels;}img_t;
img_timg_create(void);voidimg_destroy(img_t*img);intimg_resize(img_t*img,unsignedintwidth,unsignedintheight,uint8_tfillcolor);intimg_set_pixel(img_t*img,unsignedintx,unsignedinty,uint8_tcolor);intimg_get_pixel(img_t*img,unsignedintx,unsignedinty,uint8_t*colorp);
C++:
classImage{private:unsignedintcols;unsignedintrows;uint8_t*pixels;
public:Image();~Image();intresize(unsignedintwidth,unsignedintheight,uint8_tfillcolor);intset_pixel(unsignedintx,unsignedinty,uint8_tcolor);
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 4/10
intget_pixel(unsignedintx,unsignedinty,uint8_t*colorp);};
Examplesofusage,firstinC:
img_timg=img_create();
if(img_resize(&img,640,480,0)!=0){exit(1);//quit}for(inti=0;i
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 5/10
Image::Image():cols(0),//initializationlistrows(0),pixels(NULL){//Noworktodoinconstructorbodyinthisexample://theintializationlisttookcareofit.//Allmembersnowhavesafeinitialvalues.}
AweakpointoftheC++designisthathandlingerrorsinconstructorsisquitecomplicated,sincetheyhavenoreturnvalue.Itisagoodideatoavoiddoinganythinginaconstructorthatcouldfail,forexampleanysystemcallormemoryallocation.Thisiswhyinourexampleweconstructonly0x0pixelimages,anddoourpixelallocationinImage::resize()Ifanynewfails,yourprogramwillbeterminatedimmediately.Youcanchangethisbehaviourusingexceptionsbutthatisbeyondthescopeofthisclass.(SomepeoplethinkexceptionsareaBadIdea,forexampleGoogledoesnotallowtheminanyC++code).
Destructors
Wheneveranobjectisdestroyed,eitherbygoingoutofscopeorwhendeleteiscalledonitsaddress,thedestructorisautomaticallycalled.Youputmemorydeallocationandcleanupcodeinthedestructorsoyoucannotforgettorecycleresourceswhenyouarefinishedwithanobject.Afterthedestructorfinishes,thedestructorsofanydatamembersarecalled.
Destructorshavethesamenameastheirclass,prefixedwitha'~'andtheyhavenoreturntypeorvalue.
//containstheclassdeclarationforImage#include"image.hpp"
Image::~Image(){//freeeverythingthatcouldhavebeenallocatedinsidethisobjectif(pixels!=NULL){delete[]pixels;}}
Creatinganddestroyingobjects
Objectscanbecreatedonthestack,justbydeclaringthem,andtheirmethodscalledusingdotsyntax:
Imageimg;img.resize(100,100,255);//whitesquareimage
Whenastackallocatedobjectgoesoutofscope,itsdestructoriscalledautomatically.
Objectscanalsobeallocatedontheheapusingthenewkeywordfollowedbytheclassname.newreplacesmalloc()formostpurposesinC++.newreturnsapointertoaninstanceoftheclass,somembersandmethodsareaccessedusingarrowsyntax.
Unfortunately,keepingtrackofpointerstodestructobjectsautomaticallyisquitecostly,soheapallocatedobjectsmustbedestroyedmanually:
Image*img=newImage;img>resize(100,100,255);//whitesquareimage//(useimage,thenwhendone)deleteimg;
OtherlanguagessuchasJavaandC#cankeeptrackofheapallocationsandsaveyouthetroubleofdeletingthings.Thisgarbagecollectionprocesscanbeverygoodforcoderobustness,butslowsthingsdownabit.
InC++thebasicmemorysanitationstrategyis(i)writethoroughdestructorsand(ii)usestack
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 6/10
variableswheneverpossible.Rememberyourstackissmallsobigthingsgoontheheap.Agoodapproachistohaveasmallstackallocatedwrapper/headerobjectforeachofyourheapallocatedbigthings,sothatwhenthewrapperobjectgoesoutofscopeitsdestructorcleansupproperly.TheImageclassfollowsthispattern.
Defaultconstructors
Aconstructorthattakesnoargumentsiscalledadefaultconstructor.Ifyoudonotspecifyanyconstructorforyourclass,adefaultconstructorisgeneratedautomaticallythatsimplycallstheconstructorsofalldatamembersoftheclass.Thebuiltintypes(int,float,etc)havedefaultconstructorsthatallocatespaceonly:theirvaluesareleftinitialized,likeinC.
Creatingarraysofobjects
Newanddeletehaveconvenientarrayforms,whichcanbeusedwithbuiltintypesandanyobjectthathasadefaultconstructor.
int*arr=newint[100];//(useintarray,thenwhendone)delete[]arr;
Forobjects,thedefaultconstructoriscalledforeveryiteminthearray.Similarlydelete[]callsthedestructoroneachiteminthearraybeforefreeingtheentirearray.
Bubble*bubbles=newBubble[100];//produces100bubbles,allthesame//(usebubblearray,thenwhendone)delete[]bubbles;
Teachthecontroversy
Noteveryoneisafanofnewanddelete,andthis"rant"byStanfordprofessorDavidMaziresdiscussessomeoftheissuesthatbotherpeople.Followingtheauthor'sargumentwilltestandboostyourunderstandingofhowtheywork.
Methods
Classmethodsarelikenormalfunctions,buttheycanonlybecalledthroughanobjectoftherighttype.Akeyadvantageofthisisthatyoucannotpassinthewrongkindofpointer,oranullpointer.
Methodsaredefinedbyprefixingthemethodnamewiththenameoftheclass:
#include"image.hpp"
intImage::resize(unsignedintwidth,unsignedintheight,uint8_tfillcolor){//dotheworkhere//...return0;}
intImage::set_pixel(unsignedintx,unsignedinty,uint8_tcolor){//dotheworkhere//...return0;}
//(etc)
Insideaclass'smethods,allthemembersoftheclassareavailableusingjusttheirnames:
intImage::set_pixel(unsignedintx,unsignedinty,uint8_tcolor){//x,y,andcolorarelocalvariables//pixelsandcolsaremembersofthisobjectpixels[y*cols+x]=color;
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 7/10
return0;}
Incaseamethodneedstoknowwhichobjectitwascalledon,apointercalledthisalwaysexists.thispointstotheobjectonwhichthemethodwascalled.Sothiscodeisidenticaltotheabove:
intImage::set_pixel(unsignedintx,unsignedinty,uint8_tcolor){//x,y,andcolorarelocalvariables//pixelsandcolsaremembersofthisobject//socanbeaccessedthroughthe'this'pointerthis>pixels[y*this>cols+x]=color;return0;}
Insideanobject'smethods,itsothermethodsarealsoavailableusingtheirnamealone,orthroughthethispointer:
voidImage::set_grey_all_over(void){for(inty=0;yrowsfor(intx=0;xcolsset_pixel(x,y,128);//this>set_pixel()}
Onceanobjectisconstructed,itsdatamembersandmethodsareaccessedusingdotorarrowsyntax,justlikestructures,exceptthatnowwecanaccessanobject'smethodstooperateonit:
Imagei();i.resize(640,480,0);i.set_pixel(100,100,255);
Image*j=newImage();j>resize(640,480,0);j>set_pixel(100,100,255);
Task2:Save&LoadExtendyourImageclassbyaddingsave()andload()methods.Thefileformatisuptoyou.Itcanbetextorbinary,aslongastheload()loadsthesave()'dformatcorrectly.
Requirements
1. WriteanewC++sourcefile"image2.cpp"thatcontainsacompleteimplementationoftheImageclassdeclaredintheprovidedC++headerfile"image2.hpp".
2. Yourfilemustinclude"image2.hpp"withoutanymodifications.3. Writeyourownmain()functionfortestingyourclass,butputitinanothersourcefile:do
notdefinemain()in"image2.cpp"asthiswillinterferewiththeservertest.
Submission
Addandcommitthesinglefile"image2.cpp"toyourrepo.
Guide
SeeLab6forfileI/Otutorialandexamples.
Task3:Alternateimplementationusing2DarraysChangetheinternalrepresentationoftheimageinyourImageclass,withoutchangingtheexternalinterface.
Wewilluseamultidimensionalarraytostorepixelsinsteadoftheonedimensionalpixelarraywehaveusedsofar.
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 8/10
Theprocessofrevisingyourimplementationwithoutchangingtheinterfaceorexternalbehaviouriscalledrefactoringandcanbeveryimportantforkeepingcodemaintainable,particularlyafteraperiodofaddingalotoffeaturesorbugfixes.Tidyingupamessyimplementationbeforeitgetstoocomplicatedformortalstounderstandisusefulwork.Ontheotherhandyoushouldresisttinkeringforthesakeofit:youriskintroducingbugs.
Requirements
Thesuppliedfile"image3.hpp"differsfrom"image2.hpp"onlyinthatitdeclarestheprivatepixeldatapointertobeoftypeuint8_t**.YoumustreimplementtheImageclassusinga2Darray.Thiswillmakememoryallocationcodealittlemorecomplex(seetheGuidebelow),butmakeaccessingpixelseasierandarguablymakethecodemorereadable.Certainimageoperationsyouimplementedinanearlierlabcouldbefasteroreasierusing2Darrays:youdonothavetoimplementthemhere,butyoushouldthinkaboutwhichoneswouldbenefit.
1. WriteanewC++sourcefile"image3.cpp"thatcontainsacompleteimplementationoftheImageclassdeclaredintheprovidedC++headerfile"image3.hpp".
2. Yourfilemustinclude"image3.hpp"withoutanymodifications.3. Notethatsincetheinterfaceoftheclass(i.e.thepublicmethods)didnotchange,youcan
usethesamemain()programtotestitasfortheprevioustasks.Makesurenomain()functionexistsin"image3.cpp".
Caution
save()andload()needsomecarefulthought.Favourcorrectnessoverspeed,buttrynottomaketoomanysystemcalls:theyareslow.
Submission
Addandcommitthesinglefile"image3.cpp"toyourrepo.
Guide
CandC++supportmultidimensionalarrays.Thesyntaxisverysimplebuttheunderlyingmodelisalittlecomplex.Considerthesearrays,wherea2Darrayisdeclaredandusedinthewayyoumightguessbyextrapolatingfromthe1Dcase:
intA[16];//1Darrayof16elementsintB[4][4];//2Darrayof4x4elements
//setseveryelementinAfor(inta=0;a
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 9/10
'A'isoftypearrayofint.'B'isoftypearrayofarrayofint.Youcanseethatthereissomeoverheadinusingthe2Darray,aswerequiremorememoryspaceandatwosteplookuptofindtheintegerofinterest.
Moredimensions
Thearraydeclarationandaccesssyntaxworksforarbitrarynumbersofdimensions:
intC[3][3][3];//3Darrayof9intsintD[20][5][10][4];//4Darrayof20*5*10*4ints
C[0][0][0]=99;D[101][2][1][0]=99;
Inpractice,arraysofmorethan3dimensionsarerarelyused.
Building2Darraysontheheap
Theexamplesaboveshowmultidimensionalarraysallocatedonthestack.Theycanalsobeallocatedmanuallyontheheap.ThisexamplebuildsarraysAandBontheheap(omittingerrorchecking)inC:
int*A=malloc(16*sizeof(int));
int**B=malloc(4*sizeof(int*));
14/05/2015 CMPT127Lab9
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/ 10/10
for(inti=0;i