Professional Documents
Culture Documents
CMPT127Lab9
Lab9:C++classes
classesandobjects,constructorsanddestructors,refactoring
Goals
Afterthislabyouwillbeableto
1. Useclassesinplaceofstructs.
2. Writeconstructorsanddestructorsforclasses.
3. Usetwodimensionalarrays.
4. Refactorcode.
Apartfromteachingyoutouseclassesand2darrays,thislabisdesignedtohaveyouwork
repeatedlyonthesamecode.Bynowyoushouldbereadingandwritingcodemuchmore
quicklythanatthebeginningoftheclass.Youshouldalsousingyourtexteditormoreexpertly,
forexampleusingsearchandreplace,movingaroundquicklyinthefile,cuttingandpastinglines
usingkeystrokes,etc.Youwillspendmanyhoursinyourtexteditorduringyourdegreeand
beyond:youshouldmasterit.
Refactoringcode(Task3)isanactivitythatexercisesyoureditorkungfu,andwillnottaketoo
longifyouusetheeditorwell.
Setup
Notethattheseinstructionsnolongerincludeallsteps.Youshouldknowhowtodothese
thingsbynow.Ifindoubt,refertopreviouslabinstructions.
Intheterminal:
1. Addthenewdirectory'9'totherootdirectoryofyourrepository.Thiswillbethe
workingdirectoryforalltheinstructionsbelow.
2. FetchthenewmaterialforLab9,storedinacompressedtarball:
$wgethttp://www.cs.sfu.ca/~vaughan/lab9.tgz
3. Expandthearchiveintotheworkingdirectory:
$tarxzvflab9.tgz
IntroducingC++
C++extendstheClanguagewithsupportforclassestosupportObjectOrientedProgramming,
andtemplatestosupportGenericProgramming.Thisweekwewilllookatclasses,butfirsta
summaryoftheworkflowchangesyouneedtouseC++.
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.Youwill
needtoreadthenotesaboveandconstructyourowncompilecommands.
AC++primerforCprogrammers
HereisaverygoodandconciseintroductiontoC++forCprogrammers.byProf.TomAnderson
oftheUniversityofWashington.
Prof.AndersonhasstrongopinionsabouttheusefulandlessusefulpartsofC++,anddraws
yourattentiontothemostimportantpartsinlessthan12pages.Thedocumentisdatedinsome
ways,butmostoftheadviceisexcellent.
Thingstodo:
1. ReadSections1through3carefully:theywillhelpwithyourTasksthisweek.
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
1/10
14/05/2015
CMPT127Lab9
2. ReadSections4and5atyourleisure,andrememberthatopinionsvarywildlyon
thissubject,andthingschangeovertime.
3. NotethattheStandardTemplateLibrary(STL)isnowmatureandsupportedby
mostcompilers,andyoucanandshoulduseitwithconfidence.Wewillshowyou
thebasicsoftheSTLinalaterlab.
Notethatyoureallyareexpectedtoreadthedocument,andthefollowinginstructionsmaynot
beenoughbythemselvestohelpyousolvethetasks.Anothergoalofthislab(andtheclass)is
toencourageyoutoreadaroundyoursubjectsandfeelpersonalresponsibilityforlearning.
**STOP**READTHEPRIMERDOCUMENTBEFORECONTINUING**
Task1:Imageclass
WewilldevelopaC++program,usingideasfamiliarfrompreviouslabsplusnewsyntaxfor
creatingclasses.
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,extendedfromtheonewedeveloped
inanearlierlab:
typedefstructimage{
unsignedintcols;
unsignedintrows;
uint8_t*pixels;
}img_t;
/*Returnsanimg_tstructurecontaining0x0pixels.*/
img_timg_create(void);
/*Freesallmemoryallocatedforimg*/
voidimg_destroy(img_t*img);
/*Changesthesizeofanimage,allocatingmemoryasnecessary,and
settingallpixelstofillcolor.Returns0onsuccess,oranonzeroerrorcode.*/
intimg_resize(img_t*img,unsignedintwidth,unsignedintheight,uint8_tfillcolor);
/*Setsthecolorofthepixelat(x,y)tocolor.Returns0onsuccess,elseanonzero
errorcode.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
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
2/10
14/05/2015
CMPT127Lab9
2. Thefunctionsoperatingonimagestructureswouldbemethodsoftheimageclass,and
wouldnotneedthe"img_"prefix.
3. Imageclassmethodsdononeedapointertotheimagedatastructure,sincethey
automaticallyhaveathispointertotheobjectonwhichthemethodwascalled.
4. Thefieldsofthestructwouldnotbeaccessiblefromoutsidetheclass:animagecouldonly
bemodfifiedusingitsmethods.
5. img_create()wouldbeaconstructor
6. img_destroy()wouldbeadestructor
HereistheC++version:
classImage{
private:
unsignedintcols;
unsignedintrows;
uint8_t*pixels;
public:
/*Constructsanimageof0x0pixels.*/
Image();
/*Freesallmemoryallocatedforimg*/
~Image();
/*Changesthesizeofanimage,allocatingmemoryasnecessary,and
settingallpixelstofillcolor.Returns0onsuccess,oranonzeroerrorcode.*/
intresize(unsignedintwidth,unsignedintheight,uint8_tfillcolor);
/*Setsthecolorofthepixelat(x,y)tocolor.Returns0onsuccess,elseanonzero
errorcode.If(x,y)isnotavalidpixel,thecallfailsandtheimagedoesnotchange.*/
intset_pixel(unsignedintx,unsignedinty,uint8_tcolor);
/*Getsthecolorofthepixelat(x,y)andstoresattheaddresspointedto
bycolorp.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);
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
3/10
14/05/2015
CMPT127Lab9
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<100;i++)
{
img_set_pixel(&img,
rand()%640,
rand()%480,
rand()%256);
}
//outputtheimageheresomehow
//...
img_destroy(&img);//mustnotforgetthis
thenC++:
Imageimg;
if(img.resize(640,480,0)!=0)
{
exit(1);//quit
}
for(inti=0;i<100;i++)
{
img.set_pixel(rand()%640,
rand()%480,
rand()%256);
}
//outputtheimageheresomehow
//...
//imgdestructoriscalledwhenimggoesoutofscope.
Constructorsanddestructors
WehaveconsistentlyusedX_create()andX_destroy()functionswhendealingwithstructures.
Thisisaverycommondesignpatternfordoingallocationanddeallocationcleanly.This
techniquebecamesocommoninCandissousefulthatitisbuiltintoC++intheformof
constructorsanddestructors.
Constructors
Wheneveraninstanceofaclass(anobject)iscreated,itsconstructorisautomaticallycalled.
Youputinitializationcodeinsidetheconstructor,sothatallinstanceshavetheirdatamembers
initializedproperlybeforetheycanbeused.
Constructorshavethesamenameastheirclass,andtheyhavenoreturntypeorvalue.
Whenaconstructoriscalled,theconstructorsofalltheclass'sdatamembersarecalledfirst
automatically,sotheyarereadyforuseintheconstructor.Thereisaspecialsyntaxforgiving
argumentstothesedatamemberconstructors,calledtheinitializationlist:
//containstheclassdeclarationforImage
#include"image.hpp"
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
4/10
14/05/2015
CMPT127Lab9
Image::Image()
:cols(0),//initializationlist
rows(0),
pixels(NULL)
{
//Noworktodoinconstructorbodyinthisexample:
//theintializationlisttookcareofit.
//Allmembersnowhavesafeinitialvalues.
}
AweakpointoftheC++designisthathandlingerrorsinconstructorsisquitecomplicated,since
theyhavenoreturnvalue.Itisagoodideatoavoiddoinganythinginaconstructorthatcouldfail,
forexampleanysystemcallormemoryallocation.Thisiswhyinourexampleweconstructonly
0x0pixelimages,anddoourpixelallocationinImage::resize()Ifanynewfails,yourprogramwill
beterminatedimmediately.Youcanchangethisbehaviourusingexceptionsbutthatisbeyond
thescopeofthisclass.(SomepeoplethinkexceptionsareaBadIdea,forexampleGoogledoes
notallowtheminanyC++code).
Destructors
Wheneveranobjectisdestroyed,eitherbygoingoutofscopeorwhendeleteiscalledonits
address,thedestructorisautomaticallycalled.Youputmemorydeallocationandcleanupcode
inthedestructorsoyoucannotforgettorecycleresourceswhenyouarefinishedwithanobject.
Afterthedestructorfinishes,thedestructorsofanydatamembersarecalled.
Destructorshavethesamenameastheirclass,prefixedwitha'~'andtheyhavenoreturntype
orvalue.
//containstheclassdeclarationforImage
#include"image.hpp"
Image::~Image()
{
//freeeverythingthatcouldhavebeenallocatedinsidethisobject
if(pixels!=NULL)
{
delete[]pixels;
}
}
Creatinganddestroyingobjects
Objectscanbecreatedonthestack,justbydeclaringthem,andtheirmethodscalledusingdot
syntax:
Imageimg;
img.resize(100,100,255);//whitesquareimage
Whenastackallocatedobjectgoesoutofscope,itsdestructoriscalledautomatically.
Objectscanalsobeallocatedontheheapusingthenewkeywordfollowedbytheclassname.
newreplacesmalloc()formostpurposesinC++.newreturnsapointertoaninstanceofthe
class,somembersandmethodsareaccessedusingarrowsyntax.
Unfortunately,keepingtrackofpointerstodestructobjectsautomaticallyisquitecostly,soheap
allocatedobjectsmustbedestroyedmanually:
Image*img=newImage;
img>resize(100,100,255);//whitesquareimage
//(useimage,thenwhendone)
deleteimg;
OtherlanguagessuchasJavaandC#cankeeptrackofheapallocationsandsaveyouthe
troubleofdeletingthings.Thisgarbagecollectionprocesscanbeverygoodforcoderobustness,
butslowsthingsdownabit.
InC++thebasicmemorysanitationstrategyis(i)writethoroughdestructorsand(ii)usestack
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
5/10
14/05/2015
CMPT127Lab9
variableswheneverpossible.Rememberyourstackissmallsobigthingsgoontheheap.A
goodapproachistohaveasmallstackallocatedwrapper/headerobjectforeachofyourheap
allocatedbigthings,sothatwhenthewrapperobjectgoesoutofscopeitsdestructorcleansup
properly.TheImageclassfollowsthispattern.
Defaultconstructors
Aconstructorthattakesnoargumentsiscalledadefaultconstructor.Ifyoudonotspecifyany
constructorforyourclass,adefaultconstructorisgeneratedautomaticallythatsimplycallsthe
constructorsofalldatamembersoftheclass.Thebuiltintypes(int,float,etc)havedefault
constructorsthatallocatespaceonly:theirvaluesareleftinitialized,likeinC.
Creatingarraysofobjects
Newanddeletehaveconvenientarrayforms,whichcanbeusedwithbuiltintypesandany
objectthathasadefaultconstructor.
int*arr=newint[100];
//(useintarray,thenwhendone)
delete[]arr;
Forobjects,thedefaultconstructoriscalledforeveryiteminthearray.Similarlydelete[]calls
thedestructoroneachiteminthearraybeforefreeingtheentirearray.
Bubble*bubbles=newBubble[100];//produces100bubbles,allthesame
//(usebubblearray,thenwhendone)
delete[]bubbles;
Teachthecontroversy
Noteveryoneisafanofnewanddelete,andthis"rant"byStanfordprofessorDavidMazires
discussessomeoftheissuesthatbotherpeople.Followingtheauthor'sargumentwilltestand
boostyourunderstandingofhowtheywork.
Methods
Classmethodsarelikenormalfunctions,buttheycanonlybecalledthroughanobjectofthe
righttype.Akeyadvantageofthisisthatyoucannotpassinthewrongkindofpointer,oranull
pointer.
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
//pixelsandcolsaremembersofthisobject
pixels[y*cols+x]=color;
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
6/10
14/05/2015
CMPT127Lab9
return0;
}
Incaseamethodneedstoknowwhichobjectitwascalledon,apointercalledthisalways
exists.thispointstotheobjectonwhichthemethodwascalled.Sothiscodeisidenticaltothe
above:
intImage::set_pixel(unsignedintx,unsignedinty,uint8_tcolor)
{
//x,y,andcolorarelocalvariables
//pixelsandcolsaremembersofthisobject
//socanbeaccessedthroughthe'this'pointer
this>pixels[y*this>cols+x]=color;
return0;
}
Insideanobject'smethods,itsothermethodsarealsoavailableusingtheirnamealone,or
throughthethispointer:
voidImage::set_grey_all_over(void)
{
for(inty=0;y<rows;y++)//this>rows
for(intx=0;x<cols;x++)//this>cols
set_pixel(x,y,128);//this>set_pixel()
}
Onceanobjectisconstructed,itsdatamembersandmethodsareaccessedusingdotorarrow
syntax,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&Load
ExtendyourImageclassbyaddingsave()andload()methods.Thefileformatisuptoyou.Itcan
betextorbinary,aslongastheload()loadsthesave()'dformatcorrectly.
Requirements
1. WriteanewC++sourcefile"image2.cpp"thatcontainsacompleteimplementationofthe
ImageclassdeclaredintheprovidedC++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:Alternateimplementationusing2Darrays
ChangetheinternalrepresentationoftheimageinyourImageclass,withoutchangingthe
externalinterface.
Wewilluseamultidimensionalarraytostorepixelsinsteadoftheonedimensionalpixelarray
wehaveusedsofar.
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
7/10
14/05/2015
CMPT127Lab9
Theprocessofrevisingyourimplementationwithoutchangingtheinterfaceorexternalbehaviour
iscalledrefactoringandcanbeveryimportantforkeepingcodemaintainable,particularlyaftera
periodofaddingalotoffeaturesorbugfixes.Tidyingupamessyimplementationbeforeitgets
toocomplicatedformortalstounderstandisusefulwork.Ontheotherhandyoushouldresist
tinkeringforthesakeofit:youriskintroducingbugs.
Requirements
Thesuppliedfile"image3.hpp"differsfrom"image2.hpp"onlyinthatitdeclarestheprivate
pixeldatapointertobeoftypeuint8_t**.YoumustreimplementtheImageclassusinga
2Darray.Thiswillmakememoryallocationcodealittlemorecomplex(seetheGuide
below),butmakeaccessingpixelseasierandarguablymakethecodemorereadable.
Certainimageoperationsyouimplementedinanearlierlabcouldbefasteroreasierusing
2Darrays:youdonothavetoimplementthemhere,butyoushouldthinkaboutwhich
oneswouldbenefit.
1. WriteanewC++sourcefile"image3.cpp"thatcontainsacompleteimplementationofthe
ImageclassdeclaredintheprovidedC++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,buttrynottomake
toomanysystemcalls:theyareslow.
Submission
Addandcommitthesinglefile"image3.cpp"toyourrepo.
Guide
CandC++supportmultidimensionalarrays.Thesyntaxisverysimplebuttheunderlyingmodel
isalittlecomplex.Considerthesearrays,wherea2Darrayisdeclaredandusedinthewayyou
mightguessbyextrapolatingfromthe1Dcase:
intA[16];//1Darrayof16elements
intB[4][4];//2Darrayof4x4elements
//setseveryelementinA
for(inta=0;a<16;a++)
{
A[a]=99;
}
//setseveryelementinB
for(inty=0;y<4;y++)
{
for(intx=0;x<4;x++)
{
B[y][x]=99;
}
}
Thememorylayoutforthesearraysisquitedifferent,asshowninthefigure:
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
8/10
14/05/2015
CMPT127Lab9
'A'isoftypearrayofint.'B'isoftypearrayofarrayofint.Youcanseethatthereissome
overheadinusingthe2Darray,aswerequiremorememoryspaceandatwosteplookuptofind
theintegerofinterest.
Moredimensions
Thearraydeclarationandaccesssyntaxworksforarbitrarynumbersofdimensions:
intC[3][3][3];//3Darrayof9ints
intD[20][5][10][4];//4Darrayof20*5*10*4ints
C[0][0][0]=99;
D[101][2][1][0]=99;
Inpractice,arraysofmorethan3dimensionsarerarelyused.
Building2Darraysontheheap
Theexamplesaboveshowmultidimensionalarraysallocatedonthestack.Theycanalsobe
allocatedmanuallyontheheap.ThisexamplebuildsarraysAandBontheheap(omittingerror
checking)inC:
int*A=malloc(16*sizeof(int));
int**B=malloc(4*sizeof(int*));
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
9/10
14/05/2015
CMPT127Lab9
for(inti=0;i<4;i++)
{
B[i]=malloc(4*sizeof(int));
}
Thisresultsinthesamememorylayoutpictureasabove,exceptthatallthearraysareinthe
heap:onlypointersAandBareonthestack.
ThesamethinginC++styleusingnew:
int*A=newint[16];
int**B=newint*[4];
for(inti=0;i<4;i++)
{
B[i]=newint[4];
}
Whilethiscreationprocessisabitlaborious,accessingthesearraysoncecreatedissimpleand
almostasfastas1Darrays,so2Darraysdogetusedquitealotinpractice.
Whenmultidimensionalarraysarebuiltupmanuallyinthisway,youcancheaplyreorderthe
higherdimensionsofthearray(e.g.B[y])byswappingthepointerstheycontain,withouttouching
thecontentsofthelowerdimensions(e.g.B[*][x]).Iftheelementsstoredinthelowestdimension
arenumerousand/orlarge,thiscanmakeabigdifferenceinperformance.
Labcomplete.Backtothelistoflabs.
http://www.cs.sfu.ca/CourseCentral/127/vaughan/lab/9/
10/10