Anda di halaman 1dari 18

CS106L Spring 2009

Handout #26 May 19, 2009

Operator Overloading
_________________________________________________________________________________________________________

Introduction One of C++'s most po erfu! features is operator overloading, t"e a#i!ity to spe$ify "o operators norma!!y app!i$a#!e to primiti%e types $an intera$t it" $ustom $!asses& Operator o%er!oading is u#i'uitous in professiona! C++ $ode and, in fa$t, you'%e #een e(posed to operator o%er!oading sin$e t"e #eginning of CS106L& )sed $orre$t!y, operator o%er!oading $an ma*e your programs more $on$ise, more reada#!e, and more temp!ate+friend!y& ,"is "andout dis$usses genera! topi$s in operator o%er!oading, demonstrating "o to o%er!oad some of t"e more $ommon operators& -t a!so in$!udes imp!ementation tri$*s and pitfa!!s to #e a are of "en o%er!oading operators& Ho e%er, it is not a $omp!ete treatment of t"e materia!, so #e sure to $onsu!t a referen$e for some more ad%an$ed topi$s in operator o%er!oading& A Word on Correctness - ou!d #e remiss to dis$uss operator o%er!oading it"out first prefa$ing it it" a arning. operator o%er!oading is a dou#!e+edged s ord& /"en used $orre$t!y, operator o%er!oading $an !ead to intuiti%e, temp!ate+friend!y $ode t"at e!egant!y performs $omp!e( operations #e"ind t"e s$enes& Ho e%er, in$orre$t!y o%er!oaded operators $an !ead to in$redi#!y su#t!e #ugs 0 1ust t"in* of t"e pro#!ems asso$iated it" t"e assignment operator& 2o t"at e're de!%ing deeper into operator o%er!oading, you'!! en$ounter more potentia! for t"ese sorts of mista*es& Operator o%er!oading $an #e more dangerous t"an ot"er parts of t"e C++ !i#rary #e$ause in$orre$t!y+ o%er!oaded operators $an !ead to $ode t"at is 3%isua!!y $orre$t4 5it 1ust 3!oo*s rig"t46 #ut t"at $ontains serious errors& Sin$e you're redefining #asi$ operators, t"e mista*es you'!! ma*e mig"t s"o up in seeming!y "arm!ess !ines of $ode !i*e myString += myOtherString or myIterator->value = 0& ,"us, "en o%er!oading operators, you s"ou!d ma*e sure to "ea%i!y test t"e o%er!oaded operators in iso!ation #efore using t"em in genera! $ode& 7dditiona!!y, operator o%er!oading $an #e dangerous #e$ause of C++'s genera! p"i!osop"y of 3!ea%e it to t"e programmers to de$ide "at's rig"t&4 /"en o%er!oading operators, you "a%e t"e f!e(i#i!ity to define "ate%er parameter and returns types you ant& 8or e(amp!e, you $an define t"e *= operator so t"at e(pressions !i*e myVector *= myScalar is defined& Ho e%er, t"is f!e(i#i!ity a!so means you $an define nonsensi$a! operations !i*e myVector = myInt / myString& ,"us, "en o%er!oading operators, you s"ou!d #e sure t"at your operations are semantically meaningful 0 t"ey ma*e sense to a "uman reader& 8urt"ermore, it's easy to o%er!oad an operator #ut pro%ide t"e rong return type& 8or e(amp!e, you mig"t pro%ide an o%er!oaded in$rement operator su$" t"at t"e e(pression myClass++ doesn't return a %a!ue& Ho e%er, "en app!ied to #asi$ types, t"e in$rement operator does return a %a!ue, t"e %a!ue t"e %aria#!e "ad #efore t"e in$rement, and temp!ate $ode e(pe$ting t"e e(pression myOtherClass = myClass++ to #e meaningfu! i!! fai! to $ompi!e if you forget t"is& )!timate!y, remem#er t"at you are trying to as$ri#e meaning to operators t"at #y defau!t on!y app!y to primiti%e types& 7 good ru!e of t"um# is to define your o%er!oaded operators to "a%e t"e same properties and returns types t"ey "a%e "en app!ied to ints& ,"us t"e e(pression one == two s"ou!d return a bool indi$ating "et"er one and two are e'ui%a!ent and s"ou!d return t"e same resu!t if e "ad ritten

+1+

two == one& -n s"ort, operator o%er!oading is a

onderfu!!y po erfu! too! t"at $an simp!ify your $ode in remar*a#!e ays& Ho e%er, as it" a!! parts of C++, operator o%er!oading $arries a good dea! of ris* and re'uires you to #e more $riti$a! of your $ode& General Operator Overloading Principles ,"ere are t o o%erar$"ing purposes of operator o%er!oading& 8irst, operator o%er!oading ena#!es your $ustom $!asses to a$t !i*e primiti%e types& ,"at is, if you "a%e a $!ass !i*e vector t"at mimi$s a standard C++ array, you $an use array notation to a$$ess indi%idua! e!ements& Simi!ar!y, "en designing a $!ass en$apsu!ating a mat"emati$a! entity 5for e(amp!e, a $omp!e( num#er6, #asi$ numeri$a! operators !i*e +, -, and * s"ou!d or* $orre$t!y& Se$ond, operator o%er!oading ena#!es your $ode to intera$t $orre$t!y it" temp!ate and !i#rary $ode& 8or e(amp!e, you $an o%er!oad t"e operator to ma*e a $!ass $ompati#!e it" t"e -OStream !i#rary& ,o define an o%er!oaded operator, you de$!are a fun$tion "ose name is o!erator op, "ere op represents "ate%er operator you're o%er!oading& ,"us t"e o%er!oaded assignment operator is o!erator =, "i!e t"e o%er!oaded operator is o!erator & C++ o%er!oads operators #y rep!a$ing instan$es of ea$" operator it" $a!!s to its o!erator fun$tion& So, for e(amp!e, if you rite $ode !i*e t"is.
string one" two" three# one = two + three#

-t's e'ui%a!ent to
string one" two" three# one$o!erator =%o!erator+%two" three&&#

,"e se$ond %ersion, "i!e synta$ti$a!!y !ega!, is e(treme!y rare in pra$ti$e sin$e t"e point of operator o%er!oading is to ma*e t"e synta( more intuiti%e& /"en o%er!oading operators, you $annot define #rand+ne operators !i*e ' or (& 7fter a!!, C++ ou!dn't *no t"e asso$iati%ity or proper synta( for t"e fun$tion 5e&g& is one ' two + three interpreted as %one ' two& + three or one ' %two + three&96 7dditiona!!y, you $annot o%er!oad any of t"e fo!!o ing operators, #e$ause t"ey are needed at $ompi!e+time.
)) $ +) $* si.eo/ ty!ei0 *yClass))value one$value a > b + -, ) , a$*myClass-tr# si.eo/%*yClass& ty!ei0%*yClass&

S$ope reso!ution Mem#er se!e$tion ,ernary $onditiona! :ointer+to+mem#er se!e$tion 5#eyond t"e s$ope of t"is $!ass6 Si;e of o#1e$t <untime type information operator 5#eyond t"e s$ope of t"is $!ass6

=eyond t"ese restri$tions, "o e%er, you're free to o%er!oad any operators you see fit>

+2+

Overloading Bracket Operators Let's #egin our des$ent into t"e rea!m of operator o%er!oading #y dis$ussing t"e o%er!oaded #ra$*et 1 2 operator& ?ou'%e #een using t"e o%er!oaded #ra$*et operator e%er sin$e you en$ountered t"e string and vector $!asses& 8or e(amp!e, t"e fo!!o ing $ode uses t"e vector's o%er!oaded #ra$*ets.
/or%int i = 0# i myVector$si.e%&# i++& myVector1i2 = ,34#

-n t"e a#o%e e(amp!e, "i!e it !oo*s !i*e e're treating t"e vector as a primiti%e array, e are instead $a!!ing t"e fun$tion o!erator 12 it" i as t"e parameter& ,"us t"e a#o%e $ode is e'ui%a!ent to
/or%int i = 0# i myVector$si.e%&# i++& myVector$o!erator 12%i& = ,34#

,o rite a $ustom #ra$*et operator, you rite a mem#er fun$tion $a!!ed o!erator 12 t"at a$$epts as its parameter t"e e!ement t"at goes inside t"e #ra$*ets& 2ote t"at "i!e t"is parameter $an #e of any type 5t"in* of t"e S,L ma!6, you $an on!y "a%e a sing!e %a!ue inside t"e #ra$*ets& /"en riting o!erator 12, as it" a!! o%er!oaded operators, you're free to return o#1e$ts of "ate%er type you'd !i*e& Ho e%er, remem#er t"at "en o%er!oading operators, it's essentia! to maintain t"e same fun$tiona!ity you'd e(pe$t from t"e natura!!y+o$$urring uses of t"e #ra$*et operator& ,"us, in a!most a!! $ases, you s"ou!d "a%e t"e #ra$*et operators return a referen$e to data t"at's stored in your $!ass& 8or e(amp!e, "ere's one possi#!e prototype of t"e C++ string's #ra$*et operator.
char5 o!erator 12 %int !osition&#

2ote t"at sin$e t"e #ra$*ets return a referen$e to an e!ement, you s"ou!d a!most a! ays pro%ide a const+ o%er!oaded %ersion of t"e #ra$*et operator& ,"us t"e string a!so "as a mem#er fun$tion t"at !oo*s somet"ing !i*e t"is.
const char5 o!erator 12 %int !osition& const#

7not"er important detai! to *eep in mind is t"at "en riting t"e #ra$*et operator, it's tota!!y !ega! to modify t"e under!ying $ontainer in response to a re'uest& 8or e(amp!e, it" t"e S,L ma!, o!erator 12 i!! si!ent!y $reate a ne o#1e$t and return a referen$e to it if t"e o#1e$t isn't a!ready in t"e ma!& ,"is is part of t"e #eauty of o%er!oaded operators 0 you're a!!o ed to perform any ne$essary steps to ensure t"at t"e operator ma*es sense& )nfortunate!y, if your $!ass en$apsu!ates a mu!tidimensiona! o#1e$t, su$" as a matri( or "ierar$"i$a! *ey+ %a!ue system, you $annot 3o%er!oad t"e 1212 operator&4 7 $!ass is on!y a!!o ed to o%er!oad one !e%e! of t"e #ra$*et synta(& ,"is is "y t"e CS106 6ri0 7@, doesn't use #ra$*et synta( for a$$ess 0 it's not !ega! to design o#1e$ts t"at dou#!y+o%er!oad 12&A

A ,"ere is a te$"ni'ue $a!!ed proxy objects t"at $an ma*e $ode a!ong t"e !ines of myOb7ect1821y2 !ega!& ,"e tri$* is to define an o!erator12 fun$tion for t"e $!ass t"at returns anot"er o#1e$t t"at itse!f o%er!oads o!erator12&

+B+

Overloading Compound Assignment Operators ,"e $ompound assignment operators are operators of t"e form op= 5for e(amp!e, += and *=6 t"at update an o#1e$t's %a!ue #ut do not o%er rite it& ,"e #asi$ prototype for a $ompound assignment operator is
*yClass5 o!erator += %const -arameter9y!e5 !aram&

/"en riting $ompound assignment operators, you need to #e ary of se!f+assignment, a!t"oug" in many $ases you $an ignore it& 8or e(amp!e, if you "ad a $!ass Vector3: t"at en$apsu!ated a %e$tor in t"ree+ dimensiona! spa$e, you $ou!d define t"e += operator as
Vector3:5 Vector3:))o!erator +=%const Vector3: 5other& ; /or%int i = 0# i <=*>COO?:I<@9AS# i++& coor0inates1i2 += other$coor0inates1i2# return *this# B

Here, sin$e e don't dea!!o$ate any memory during t"e $ompound assignment, t"is $ode on't $ause any pro#!ems& Ho e%er, "en or*ing it" t"e C++ string's += operator, sin$e t"e string needs to a!!o$ate a ne #uffer $apa#!e of "o!ding t"e $urrent string appended to itse!f, it ou!d need to "and!e t"e se!f+assignment $ase, eit"er #y e(p!i$it!y $"e$*ing for se!f+assignment or t"roug" some ot"er means& /e'!! go o%er t"is $ode !ater in t"e "andout& 2ote t"at t"e $ompound assignment operators s"ou!d return a non+const referen$e to t"e $urrent o#1e$t& <e$a!! t"at "en o%er!oading operators, you s"ou!d ma*e sure to define your operators su$" t"at t"ey or* identi$a!!y to t"e C++ #ui!t+in operators& ,"us o#s$ure #ut !ega! $ode s"ou!d $ompi!e using your o%er!oaded operators& )nfortunate!y, t"e $ode #e!o , t"oug" t"e 'uintessen$e of a#ysma! sty!e, is !ega!.
int one" two" three" /our# %one += two& += %three += /our&#

2ote t"at t"e referen$e returned #y %one += two& is t"en "a%ing its o n += operator in%o*ed& Had t"e += operator returned a const referen$e, t"is $ode ou!d "a%e #een i!!ega!& ,"us, unfortunate!y, you must ma*e sure to "a%e any assignment operator return *this as a non+const referen$e& )n!i*e t"e regu!ar assignment operator, it" t"e $ompound assignment operator it's $ommon!y meaningfu! to a$$ept o#1e$ts of different types as parameters& 8or e(amp!e, if you ere to define a Vector3: $!ass t"at en$apsu!ated a mat"emati$a! %e$tor in t"ree+dimensiona! spa$e, you mig"t ant to ma*e e(pressions !i*e myVector *= ,34 meaningfu! as a s$a!ing operation& -n t"is $ase, you'!! simp!y define an o!erator *= t"at a$$epts an int as its parameter& 7s it" o!erator 12 5and o%er!oaded operators in genera!6, you're free to spe$ify "ate%er type you'd !i*e as a parameter, t"oug" t"e operator must a$$ept a sing!e parameter& Overloading Mathematical Operators -n t"e pre%ious se$tion, e pro%ided o%er!oaded %ersions of t"e += fami!y of operators& ,"us, e $an no rite $!asses for "i$" e(pressions of t"e form one += two are %a!id& Ho e%er, t"e seeming!y e'ui%a!ent e(pression one = one + two i!! sti!! not $ompi!e, sin$e e "a%en't pro%ided an imp!ementation of t"e !one + operator&

+C+

/"en riting mat"emati$a! operators !i*e + and *, it's important to "a%e t"e return type of t"e fun$tion #e a const, non+referen$e %ersion of t"e $!ass& ,"at is, for a $!ass *yClass o%er!oading t"e + operator, t"e return type s"ou!d #e a const *yClass& ,"is may not ma*e mu$" sense, so !et's $onsider "at ou!d "appen ot"er ise& Suppose t"at e de$!ared t"e return type of t"e + operator non+const& ,"en e'd end up it" a fun$tion returning a muta#!e *yClass o#1e$t, so e $ou!d do somet"ing !i*e t"is.
%one + two& = three#

,"e a#o%e e(pression isn't !ega! for any #ui!t+in type, so e s"ou!d a%oid ma*ing it !ega! for our $ustom+ defined type& ,"e reason t"at t"e o%er!oaded arit"meti$ operators s"ou!dn't return referen$es is a #it more $omp!i$ated& Sin$e you're $reating a ne o#1e$t for t"e return %a!ue, t"e o#1e$t "as to eit"er #e on t"e sta$* or in t"e "eap& -f t"e o#1e$t is on t"e sta$*, "en t"e o%er!oaded fun$tion returns, t"e ne !y+$reated o#1e$t i!! #e $!eaned up and t"e referen$e i!! refer to in%a!id memory& -f, "o e%er, t"e memory is on t"e "eap, t"en you'd need to e(p!i$it!y dea!!o$ate t"e memory for t"e temporary o#1e$t after t"e arit"meti$& Sin$e neit"er of t"ese $ases !ead to good $ode, you s"ou!d not return referen$es from t"e arit"meti$ operators& Let's $onsider an imp!ementation of o!erator + for a CString type& CString "as t"e fo!!o ing definition.
class CString ; !ublic) /* Constructor" 0estructor" co!y constructor" assignment o!erator */ CString5 o!erator += %const CString5 other&# !rivate) char* theString# B#

/e $an t"en define o!erator += as


CString5 CString))o!erator +=%const CString5 other& ; /* @llocate s!ace /or the resulting string$ */ char* bu//er = new char1strlen%theString& + strlen%other$theString& + ,2# /* Concatenate the two strings$ */ strc!y%bu//er" theString&# strcat%bu//er" other$theString&# /* Cree ol0 memory$ */ 0elete 12 theString# theString = bu//er# return *this#

2ote t"at "i!e t"e a#o%e $ode doesn't e(p!i$it!y $"e$* for se!f+assignment, it i!! or* $orre$t!y sin$e e're $arefu! not to dea!!o$ate theString unti! after e'%e $reated t"e ne string for our CString& /e'd no !i*e to rite an imp!ementation of o!erator +& /e a!ready *no t"at e're supposed to return a const CString, and #ased on our *no !edge of parameter passing, e *no t"at e s"ou!d a$$ept as t"e parameter to o!erator + a const CString 5& ,"ere's one more #it e're forgetting,

+D+

t"oug", and t"at's to mar* t"e o!erator + fun$tion const, sin$e o!erator + $reates a ne o#1e$t and doesn't modify eit"er of t"e %a!ues used in t"e arit"meti$ statement& Ho e%er, e mig"t run into some trou#!e riting o!erator + sin$e t"e $ode for $on$atenating t o C strings is tri$*y& -f you'!! noti$e, t"oug", e a!ready "a%e a or*ing %ersion of string $on$atenation in t"e #ody of o!erator +=& ,o unify our $ode, e'!! t"erefore imp!ement o!erator + #y ma*ing a $a!! to o!erator +=& ,"e fu!! %ersion of t"is $ode is s"o n #e!o .
const CString CString))o!erator +%const CString 5other& const ; CString result = *this# // *aDe a 0ee! co!y o/ this CString$ result += other# // =se e8isting concatenation co0e$ return result# B

2o , a!! of t"e $ode for o!erator + is unified, "i$" "e!ps $ut do n on $oding errors& ,"ere is an interesting and $ommon $ase e "a%en't addressed yet 0 "at if one of t"e operands isn't of t"e same type as t"e $!ass9 8or e(amp!e, if you "a%e a *atri8 $!ass t"at en$apsu!ates a B(B matri(, as s"o n "ere.
class *atri8 ; !ublic) /* Other member /unctions$ */ *atri85 o!erator *= %0ouble scalar&# // Scale all entries !rivate) static const int *@9?IE>SIFA = 3# 0ouble entries1*@9?IE>SIFA21*@9?IE>SIFA2#

B#

2ote t"at t"ere is a defined *= operator t"at s$a!es a!! e!ements in t"e matri( #y a 0ouble fa$tor& ,"us $ode !i*e my*atri8 *= G$4,HGH is e!!+defined& Ho e%er, sin$e t"ere's no defined o!erator *, $urrent!y e $annot rite my*atri8 = my*atri8 * G$4,HGH& -nitia!!y, you mig"t t"in* t"at e $ou!d define o!erator * 1ust as e did o!erator + in t"e pre%ious e(amp!e& /"i!e t"is i!! or* in most $ases, it i!! !ead to some pro#!ems e'!! need to address !ater& 8or no , "o e%er, !et's add t"e mem#er fun$tion o!erator * to *atri8, "i$" is defined as
const *atri8 *atri8))o!erator *%0ouble scalar& const ; *y*atri8 result = *this# result *= scalar# return result# B

2o , e $an rite e(pressions !i*e my*atri8 = my*atri8 * G$4,HGH& Ho e%er, "at "appens if e rite $ode !i*e my*atri8 = G$4,HGH * my*atri89 ,"is is a semanti$a!!y meaningfu! e(pression, #ut unfortunate!y it on't $ompi!e& /"en interpreting o%er!oaded operators, C++ i!! a! ays preser%e t"e order of %a!ues in an e(pression& ,"us G$4,HGH * my*atri8 is not t"e same as

+6+

my*atri8 * G$4,HGH&A <emem#er t"at t"e reason t"at my*atri8 * G$4,HGH is !ega! is #e$ause it's e'ui%a!ent to my*atri8$o!erator *%G$4,HGH&& ,"e e(pression G$4,HGH * my*atri8, on t"e ot"er "and, is i!!ega! #e$ause C++ i!! try to e(pand it into %G$4,HGH&$o!erator *%my*atri8&,

"i$" ma*es no sense& )p to t"is point, e'%e on!y seen o%er!oaded operators as mem#er fun$tions, usua!!y #e$ause t"e operators a$t re!ati%e to some re$ei%ing o#1e$t, #ut in C++ it's a!so !ega! to define o%er!oaded operators as free fun$tions& /"en defining an o%er!oaded operator as a free fun$tion, you simp!y define a g!o#a! fun$tion named o!erator op 5 "ere op is t"e operator in 'uestion6 t"at a$$epts t"e proper num#er of parameters& /"en using t"is o%er!oaded operator in $ode, it i!! e(pand to a $a!! to t"e g!o#a! fun$tion& 8or e(amp!e, if t"ere is a g!o#a! o!erator + fun$tion, t"en t"e !ine one + two ou!d e(pand into o!erator +%one" two&& ,"is is e(a$t!y "at e need to so!%e t"is pro#!em& Let's ma*e o!erator * a free fun$tion t"at a$$epts t o parameters, a 0ouble and a *atri8, and returns a const *atri8& ,"us $ode !i*e G$4,HGH * my*atri8 i!! e(pand into $a!!s to o!erator *%G$4,HGH" my*atri8&& ,"e ne %ersion of o!erator * is defined #e!o .
const *atri8 o!erator * %0ouble scalar" const *atri85 matri8& ; *atri8 result = *matri8# matri8 *= scalar# return result# B

=ut "ere e run into t"e same pro#!em as #efore if e rite my*atri8 * G$4,HGH, sin$e e "a%en't defined a fun$tion a$$epting a *atri8 as its first parameter and an 0ouble as its se$ond& ,o fi( t"is, e'!! define a second free fun$tion o!erator * it" t"e parameters re%ersed t"at's imp!emented as a $a!! to t"e ot"er %ersion.
const *atri8 o!erator *%const *atri85 matri8" int scalar& ; return scalar * matri8# B

?ou are free to define g!o#a! operator o%er!oads for most operators, pro%ided t"at at !east one of t"e parameters is not a primiti%e type& ,"at is, you $an't define o!erator + as a free fun$tion t"at ta*es t o ints& 7!so, t"ere are a fe operators you $annot o%er!oad as free fun$tions, su$" as t"e assignment operatorE $onsu!t a referen$e for more information& One important point to noti$e a#out o%er!oading t"e mat"emati$a! operators %ersus t"e $ompound assignment operators is t"at it's $onsidera#!y faster to use t"e $ompound assignment operators o%er t"e re!ationa! operators& 2ot on!y do t"e $ompound assignment operators or* in+p!a$e 5t"at is, t"ey modify e(isting o#1e$ts6, #ut t"ey a!so return referen$es instead of fu!! o#1e$ts& 8rom a performan$e standpoint, t"is means t"at gi%en t"ese t"ree strings.
string one = I9his I# string two = Iis a I# string three = IstringJI#

Consider t"ese t o $ode snippets to $on$atenate a!! t"ree strings.


A One ma1or reason for t"is is t"at sometimes t"e arit"meti$ operators on't #e $ommutati%e& 8or e(amp!e, gi%en matri$es A and B, AB is not ne$essari!y t"e same as BA, and if C++ ere to ar#itrari!y f!ip parameters it $ou!d resu!t in some e(treme!y diffi$u!t+to+tra$* #ugs&

+F+

/* Using += */ string myString = one# myString += two# myString += three# /* Using + */ string myString = one + two + three

Odd!y, t"e se$ond %ersion of t"is $ode is $onsidera#!y s!o er t"an t"e first #e$ause t"e + operator generates temporary o#1e$ts& <emem#er t"at "en riting one + two + three, it's e'ui%a!ent to o!erator +%one" o!erator +%two" three&&& Ga$" $a!! to o!erator + returns a ne string formed #y $on$atenating t"e parameters, so t"e $ode one + two + three $reates a tota! of t o temporary string o#1e$ts 5possi#!y fe er depending on t"e $ompi!er6& ,"e first %ersion, on t"e ot"er "and, generates no temporary o#1e$ts sin$e t"e += operator or*s in+p!a$e& ,"us "i!e t"e first %ersion is !ess sig"t!y, it is signifi$ant!y faster t"an t"e se$ond %ersion& Overloading ++ and -O%er!oading t"e in$rement and de$rement operators $an #e a #it tri$*y #e$ause t"ere are t o %ersions of ea$" fun$tion 0 t"e prefi( and postfi( ++ and -- operators& <e$a!! t"at 8++ and ++8 are different operations 0 t"e first i!! e%a!uate to t"e %a!ue of 8, t"en in$rement 8, "i!e t"e se$ond i!! in$rement 8 and t"en e%a!uate to t"e updated %a!ue of 8& ?ou $an see t"is #e!o .
int 8 = 0 cout 8++ cout 8 8 = 0# cout cout ++8 8 en0l# // -rints 0 en0l# // -rints , en0l# // -rints , en0l# // -rints ,

7!t"oug" t"is distin$tion is su#t!e, it's tremendous!y important for effi$ien$y reasons& -n t"e postfi( %ersion of ++, sin$e e "a%e to return t"e %a!ue of %aria#!e as #efore it as in$remented, e'!! need to ma*e a fu!! $opy of t"e o!d %ersion and t"en return it& /it" t"e prefi( ++, sin$e e're returning t"e $urrent %a!ue of t"e %aria#!e, e $an simp!y return a referen$e to it& ,"us postfi( ++ is noti$ea#!y s!o er t"an t"e prefi( %ersion& ,"e ne(t 'uestion e need to address is "o e $an !ega!!y use ++ and -- in regu!ar $ode& )nfortunate!y, it $an get a #it $omp!i$ated& 8or e(amp!e, t"e fo!!o ing $ode is tota!!y !ega!.
int 8 = 0# ++++++++++++++8# // Increments 8 seven times$

,"is is !ega! #e$ause it's e'ui%a!ent to


++%++%++%++%++%++%++8&&&&&&#

,"us t"e %a!ue e get #a$* from t"e prefi( ++ must not #e const, or e $ou!dn't do t"is $"ained in$rementation& Ho e%er, if e use t"e postfi( %ersion of ++, as seen "ere.
8++++++++++++++# // A??O?J

+H+

/e get a $ompi!e+time error, sin$e after t"e first 8++, e're !eft it" the value of 8 #efore t"e in$rementation, rat"er t"an t"e %aria#!e 8 itse!f& ,"us t"e %a!ue returned #y t"e postfi( ++ operator must return a const o#1e$t& 2o , !et's a$tua!!y get into some $ode& )nfortunate!y, e $an't 1ust sit do n and rite o!erator ++, sin$e it's un$!ear which o!erator ++ e'd #e o%er!oading& ,o differentiate #et een t"e t o %ersions, C++ uses a #it of a "a$*. "en o%er!oading t"e prefi( %ersion of ++ or --, you simp!y rite o!erator ++ as a fun$tion t"at ta*es no parameters& ,o o%er!oad t"e postfi( %ersion, you'!! o%er!oad o!erator ++, #ut t"e o%er!oaded operator i!! a$$ept as a parameter t"e integer %a!ue 0& -n $ode, t"ese t o de$!arations !oo* !i*e
*yClass5 o!erator ++%&# // -re/i8 const *yClass o!erator ++%int 0ummy&# // -ost/i8

/e're a!!o ed to imp!ement ++ and -- in any ay e see fit& Ho e%er, one of t"e more $ommon tri$*s is to rite t"e ++ imp!ementation as a rapped $a!! to o!erator +=& 7ssuming you'%e pro%ided t"is fun$tion, e $an t"en rite t"e prefi( o!erator ++ as
*yClass5 *yClass))o!erator ++%& ; *this += ,# return *this# B

7nd t"e postfi( o!erator ++ as


const *yClass *yClass))o!erator ++%int 0ummy& ; *yClass ol0Value = *this# // Store the current value o/ the ob7ect$ *this += ,# return ol0Value# B

Overloading Relational Operators :er"aps t"e most $ommon!y o%er!oaded operators 5ot"er t"an o!erator =6 are t"e re!ationa! operators !i*e and ==& )n!i*e t"e assignment operator, #y defau!t C++ does not pro%ide re!ationa! operators for your o#1e$ts& ,"is means t"at you must e(p!i$it!y o%er!oad t"e == and re!ated operators to use t"em in $ode& ,"e prototype for t"e re!ationa! operators !oo*s !i*e t"is 5 ritten for , #ut $an #e for any of t"e re!ationa! operators6.
bool o!erator %const *yClass 5other& const#

?ou're free to $"oose any means for defining "at it means for one o#1e$t to #e 3!ess t"an4 anot"er& /"at's important is $onsisten$y& ,"at is, if one two, e s"ou!d a!so "a%e one J= two and J%one >= two&& -n fa$t, you may ant to $onsider defining 1ust t"e operator and t"en imp!ementing ==, =, J=, >, and >= as rapper $a!!s&

+9+

toring O!"ects in #$ maps )p to t"is point e'%e a%oided storing o#1e$ts as *eys in S,L ma!s& 2o t"at e'%e $o%ered operator o%er!oading, t"oug", you "a%e t"e ne$essary *no !edge to store o#1e$ts in t"e S,L ma! and set $ontainers& -nterna!!y, t"e S,L ma! and set are !ayered on #inary trees t"at use t"e re!ationa! operators to $ompare t o e!ements& @ue to some $!e%er design de$isions, S,L $ontainers and a!gorit"ms on!y re'uire t"e operator to $ompare t o o#1e$ts& ,"us, to store a $ustom $!ass inside a ma! or set, you simp!y need to o%er!oad t"e operator and t"e S,L i!! "and!e t"e rest& 8or e(amp!e, "ere's some $ode to store a -oint struct in a ma!.
struct !oint9 ; int 8" y# bool o!erator %const !oint95 other& const ; i/%8 other$8& return true# i/%8 > other$8& return /alse# return y other$y# B B# ma! !oint9" int> my*a!# // <ow worDs using the 0e/ault o!erator$

?ou $an use a simi!ar tri$* to store o#1e$ts as %a!ues in a set&


friend

2orma!!y, "en you mar* a $!ass's data mem#ers pri%ate, on!y instan$es of t"at $!ass are a!!o ed to a$$ess t"em& Ho e%er, in some $ases you mig"t ant to a!!o spe$ifi$ ot"er $!asses or fun$tions to modify pri%ate data& 8or e(amp!e, if you ere imp!ementing t"e S,L ma! and anted to pro%ide an iterator $!ass to tra%erse it, you'd ant t"at iterator to "a%e a$$ess to t"e ma!'s under!ying #inary tree& ,"ere's a s!ig"t pro#!em "ere, t"oug"& 7!t"oug" t"e iterator is an integra! $omponent of t"e ma!, !i*e a!! ot"er $!asses, t"e iterator $annot a$$ess pri%ate data and t"us $annot tra%erse t"e tree& Ho are e to reso!%e t"is pro#!em9 ?our initia! t"oug"t mig"t #e to ma*e some pu#!i$ a$$essor met"ods t"at ou!d !et t"e iterator modify t"e o#1e$t's interna! data representation& )nfortunate!y, t"is on't or* parti$u!ar!y e!!, sin$e t"en any $!ass ou!d #e a!!o ed to use t"ose fun$tions, somet"ing t"at %io!ates t"e prin$ip!e of en$apsu!ation& -nstead, to so!%e t"is pro#!em, e $an use t"e C++ /rien0 *ey ord to grant t"e iterator $!ass a$$ess to t"e ma! or set's interna!s& -nside t"e ma! de$!aration, e $an rite t"e fo!!o ing.
/rien0 class iterator# class iterator ; /* $$$ iterator im!lementation here $$$ */ B#

2o , sin$e iterator is a /rien0 of ma!, it $an read and modify t"e ma!'s pri%ate data mem#ers&

+ 10 +

Iust as e $an grant ot"er $!asses /rien0 a$$ess to a $!ass, e $an gi%e /rien0 a$$ess to g!o#a! fun$tions& 8or e(amp!e, if e "ad a free fun$tion *o0i/y*yClass t"at a$$epted a *yClass o#1e$t as a referen$e parameter, e $ou!d !et *o0i/y*yClass modify t"e interna! data of *yClass if inside t"e *yClass de$!aration e added t"e !ine
/rien0 voi0 *o0i/y*yClass%*yClass5 !aram&#

/"en using /rien0, t"ere are t o *ey points to #e a are of& 8irst, t"e /rien0 de$!aration must pre$ede t"e a$tua! imp!ementation of t"e /rien0 $!ass or fun$tion& Sin$e C++ $ompi!ers on!y ma*e a sing!e pass o%er t"e sour$e fi!e, if t"ey "a%en't seen a /rien0 de$!aration for a fun$tion or $!ass, "en t"e fun$tion or $!ass tries to modify your o#1e$t's interna!s, t"e $ompi!er i!! generate an error& Se$ond, note t"at "i!e /rien0 is 'uite usefu! in some $ir$umstan$es, it $an 'ui$*!y !ead to $ode t"at entire!y defeats t"e purpose of en$apsu!ation& =efore you grant /rien0 a$$ess to a pie$e of $ode, ma*e sure t"at t"e $ode "as a !egitimate reason to #e modifying your o#1e$t& ,"at is, don't de$!are a fun$tion /rien0 simp!y #e$ause it's easier to rite t"at ay& ,"in* of /rien0 as a ay of e(tending a $!ass definition to in$!ude ot"er pie$es of $ode& ,"e $!ass, toget"er it" a!! its /rien0 $ode, s"ou!d $omprise a !ogi$a! unit of en$apsu!ation& /"en o%er!oading any operator as a free fun$tion, you mig"t ant to $onsider gi%ing t"at fun$tion /rien0 a$$ess to your $!ass& ,"at ay, t"e fun$tions $an effi$ient!y read your o#1e$t's pri%ate data it"out "a%ing to go t"roug" getters and setters& )nfortunate!y, /rien0 does not intera$t parti$u!ar!y intuiti%e!y it" temp!ate $!asses& Suppose e ant to pro%ide a /rien0 fun$tion -KueueCrien0 for a temp!ate %ersion of t"e CS106 -Kueue& -f -KueueCrien0 is de$!ared !i*e t"is.
tem!late ty!ename 9> voi0 -KueueCrien0%const -Lueue 9>5 !L& ; // $$$ B

?ou'!! noti$e t"at -KueueCrien0 itse!f is a temp!ate fun$tion& ,"is means t"at "en de$!aring -KueueCrien0 a /rien0 of t"e temp!ate -Kueue, e'!! need to ma*e t"e /rien0 de$!aration temp!ati;ed, as s"o n "ere.
tem!late ty!ename 9> class -Kueue ; !ublic) /* $$$ */ tem!late ty!ename 9> /rien0 -KueueCrien0%const -Lueue 9>5 !L&# B#

-f you forget t"e tem!late de$!aration, t"en your $ode i!! $ompi!e $orre$t!y #ut i!! generate a !in*er error& /"i!e t"is $an #e a #it of nuisan$e, it's important to remem#er sin$e it arises fre'uent!y "en o%er!oading t"e stream operators, as you'!! see #e!o &

+ 11 +

Overloading the tream Insertion Operator Ha%e you e%er ondered "y cout IMello" worl0JI en0l is synta$ti$a!!y !ega!9 -t's A t"roug" t"e o%er!oaded operator in $on1un$tion it" ostreams& -n fa$t, t"e entire -OStream !i#rary $an #e t"oug"t of as a giganti$ !i#rary of massi%e!y o%er!oaded and >> operators& ,"e C++ -OStream !i#rary is designed to gi%e you ma(imum f!e(i#i!ity it" your input and output routines and e%en !ets you define your o n stream insertion and e(tra$tion operators& ,"is means t"at you are a!!o ed to define t"e and >> operators so t"at e(pressions !i*e cout myClass en0l and cin >> myClass are e!!+defined& Ho e%er, "en riting stream insertion and e(tra$tion operators, t"ere are "uge num#er of $onsiderations to *eep in mind, many of "i$" are #eyond t"e s$ope of t"is $!ass& ,"is ne(t se$tion i!! dis$uss #asi$ strategies for o%er!oading t"e operator, a!ong it" some !imitations of t"e simp!e approa$"& 7s it" a!! o%er!oaded operators, e need to $onsider "at t"e parameters and return type s"ou!d #e for our o%er!oaded operator& =efore $onsidering parameters, !et's t"in* of t"e return type& /e *no t"at it s"ou!d #e !ega! to $"ain stream insertions toget"er 0 t"at is, $ode !i*e cout , G en0l s"ou!d $ompi!e $orre$t!y& ,"e operator asso$iates to t"e !eft, so t"e a#o%e $ode is e'ua! to
%%%cout ,& G& en0l&%

,"us, e need t"e operator to return an ostream& 2o , e don't ant t"is stream to #e const, sin$e t"en e $ou!dn't rite $ode !i*e t"is.
cout I9his is a stringJI setw%,0& en0l#

Sin$e if cout I9his is a stringJI e%a!uated to a const o#1e$t, e $ou!dn't set t"e idt" of t"e ne(t operation to 10& Simi!ar!y, e do not ant to return t"e stream #y %a!ue& 8or e(amp!e, $onsider t"e fo!!o ing $ode snippet.
o/stream out!ut%Iout-/ile$t8tI&# out!ut I9his is a stringJI ,34 en0l#

-f out!ut I9his is a stringJI returned a $opy of t"e out!ut stream, at t"e end of t"e !ine, t"e temporary stream o#1e$t's destru$tor ou!d in%o*e and $!ose t"e fi!e "and!e, "i$" is not at a!! "at e "ad in mind> :utting t"ese t o t"ings toget"er, e see t"at t"e stream operators s"ou!d return a non+ const referen$e to "ate%er stream t"ey're referen$ing& 2o !et's $onsider "at parameters e need& /e need to *no "at stream e ant to rite to or read from, so initia!!y you mig"t t"in* t"at e'd define o%er!oaded stream operators as mem#er fun$tions t"at !oo* !i*e t"is.
class *yClass ; !ublic) ostream5 o!erator B#

%ostream5 in!ut& const#

A 7s a reminder, t"e ostream $!ass is t"e #ase $!ass for output streams& ,"is "as to do it" in"eritan$e, "i$" e'!! $o%er ne(t ee*, #ut for no 1ust rea!i;e t"at it means t"at cout, stringstream, and o/stream are a!! spe$ia!i;ations of t"e more generi$ ostream $!ass&

+ 12 +

)nfortunate!y, t"is isn't $orre$t& Consider t"e fo!!o ing t o $ode snippets.
cout myClass# myClass cout#

,"e first of t"ese t o %ersions ma*es sense, "i!e t"e se$ond is #a$* ards& )nfortunate!y, it" t"e a#o%e definition of o!erator , e'%e a$$identa!!y made t"e se$ond %ersion synta$ti$a!!y !ega!& ,"e reason is t"at t"ese t o !ines e(pand into $a!!s to
cout$o!erator %myClass&# myClass$o!erator %cout&#

,"e first of t"ese t o isn't defined, sin$e cout doesn't "a%e a mem#er fun$tion $apa#!e of riting our o#1e$t 5if it did, e ou!dn't need to rite a stream operator in t"e first p!a$e>6& Ho e%er, #ased on our pre%ious definition, t"e se$ond %ersion, "i!e semanti$a!!y in$orre$t, is synta$ti$a!!y !ega!& Some"o e need to $"ange "o e define t"e stream operator so t"at e are a!!o ed to rite cout myClass& ,o fi( t"is, e'!! ma*e t"e o%er!oaded stream operator a free fun$tion t"at ta*es t o parameters 0 an ostream to rite to and a myClass o#1e$t to rite& ,"e $ode for t"is is.
ostream5 o!erator %ostream5 stream" const *yClass5 mc& ; /* $$$ im!lementation $$$ */ return stream# B

/"i!e t"is $ode i!! or* $orre$t!y, sin$e o!erator is a free fun$tion, it doesn't "a%e a$$ess to any of t"e pri%ate data mem#ers of *yClass& ,"is $an #e a nuisan$e, sin$e e'd !i*e to dire$t!y rite t"e $ontents of *yClass out to t"e stream it"out "a%ing to go t"roug" t"e 5possi#!y ineffi$ient6 getters and setters& ,"us, e'!! de$!are o!erator a /rien0 inside t"e *yClass de$!aration, as s"o n "ere.
class *yClass ; !ublic) /* *ore /unctions$ */ /rien0 ostream5 o!erator B#

%ostream5 stream" const *yClass5 mc&#

2o , e're a!! set to do reading and riting inside t"e #ody of t"e insertion operator& -t's not parti$u!ar!y diffi$u!t to rite t"e stream insertion operator 0 a!! t"at you need to do is print out a!! of t"e meaningfu! $!ass information it" some formatting information& So, for e(amp!e, gi%en a -oint $!ass representing a point in 2+@ spa$e, e $ou!d rite t"e insertion operator as
ostream5 o!erator ; stream N%N return stream# B %ostream 5stream" const -oint 5!t& !t$8 I" I !t$y N&N#

/"i!e t"is $ode i!! or* in most $ases, t"ere are a fe spots "ere it 1ust on't or* $orre$t!y& 8or e(amp!e, suppose e rite t"e fo!!o ing $ode.
cout cout I0,G3OPQ4HR0,G3OPQ4HRI en0l# // 9o see the number o/ characters$ setw%G0& my-oint en0l#

+ 1B +

Loo*ing at t"is $ode, you'd e(pe$t t"at it ou!d $ause my-oint to #e printed out and padded it" spa$e $"ara$ters unti! it is at !east t enty $"ara$ters ide& )nfortunate!y, t"is isn't "at "appens& Sin$e o!erator rites t"e o#1e$t one pie$e at a time, t"e output i!! !oo* somet"ing !i*e t"is.
0,G3OPQ4HR0,G3OPQ4HR %0" O&

,"at's nineteen spa$es, fo!!o ed #y t"e a$tua! -oint data& ,"e pro#!em is t"at "en e in%o*e o!erator , t"e fun$tion rites a sing!e % $"ara$ter to stream& -t's t"is operation, not the Point as a whole, t"at i!! get a!igned to 20 $"ara$ters& ,"ere are many ays to $ir$um%ent t"is pro#!em, #ut per"aps t"e simp!est is to #uffer t"e output into a stringstream and t"en rite t"e $ontents of t"e stringstream to t"e destination in a sing!e operation& ,"is $an get a #it $omp!i$ated, espe$ia!!y sin$e you'!! need to $opy t"e stream formatting information o%er& /riting a $orre$t stream e(tra$tion operator 5o!erator >>6 is in$redi#!y $omp!i$ated& ?ou'!! need to remem#er a!! t"e information you read so t"at if t"e operation fai!s you $an re%ert t"e state of t"e stream to t"e state #efore t"e read operation& Simi!ar!y, you'!! need to manua!!y set t"e stream's fai! state if t"e operation fai!s& 8or more information on riting stream e(tra$tion operators, $onsu!t a referen$e& Overloading * and -> Consider t"e fo!!o ing $ode snippet.
/or%set string>))iterator itr = mySet$begin%&# itr J= mySet$en0%&# ++itr& cout *itr I has length I itr->length%& en0l#

Here, e tra%erse a set string> using iterators, printing out ea$" string and its !engt"& -nteresting!y, e%en t"oug" set iterators are not ra pointers 5t"ey're o#1e$ts $apa#!e of tra%ersing #inary trees6, t"an*s to operator o%er!oading, t"ey $an respond to t"e * and -> operators as t"oug" t"ey ere regu!ar C++ pointers& -f you $reate a $ustom $!ass t"at a$ts !i*e a C++ pointer 5per"aps a $ustom iterator or 3smart pointer,4 a topi$ e'!! return to !ater6, you $an pro%ide imp!ementations of t"e pointer dereferen$e and mem#er se!e$tion operators * and -> #y o%er!oading t"eir respe$ti%e operator fun$tions& ,"e simp!er of t"ese t o fun$tions is t"e pointer dereferen$e operator& ,o ma*e an o#1e$t t"at $an #e dereferen$ed to yie!d an o#1e$t of type 9, t"e synta( for its * operator is
95 o!erator *%& const#

?ou $an in%o*e t"e o!erator * fun$tion #y 3dereferen$ing4 t"e $ustom pointer o#1e$t& 8or e(amp!e, t"e fo!!o ing $ode.
*myCustom-ointer = ,34#

-s $omp!ete!y e'ui%a!ent to
myCustom-ointer$o!erator *%& = ,34#

=e$ause e $an assign a %a!ue to t"e resu!t of o!erator *, t"e o!erator * fun$tion s"ou!d return a referen$e&

+ 1C +

,"ere are t o ot"er points ort" noting "ere& 8irst, "o $an C++ distinguis" t"is o!erator * for pointer dereferen$e from t"e o!erator * used for mu!tip!i$ation9 ,"e ans er "as to do it" t"e num#er of parameters to t"e fun$tion& Sin$e a pointer dereferen$e is a unary operator, t"e fun$tion prototype for t"e pointer+dereferen$ing o!erator * ta*es no parameters& Had e anted to rite o!erator * for mu!tip!i$ation, e ou!d "a%e ritten a fun$tion o!erator * t"at a$$epts a parameter& Se$ond, "y o!erator * is mar*ed const9 ,"is "as to do it" t"e differen$e #et een const pointers and pointers+to+const& Suppose t"at e "a%e a const instan$e of a $ustom pointer $!ass& Sin$e t"e pointer object is const, it a$ts as t"oug" it is a const pointer rat"er t"an a pointer+to+const& Conse'uent!y, e s"ou!d #e a#!e to dereferen$e t"e o#1e$t and modify its stored pointer it"out affe$ting its constness& ,"e arro operator o!erator -> is s!ig"t!y more $omp!i$ated t"an o!erator *& -nitia!!y, you mig"t t"in* t"at o!erator -> ou!d #e a #inary operator, sin$e you use t"e arro operator in statements !i*e myClass-tr->myAlement& Ho e%er, C++ "as a rat"er $!e%er me$"anism for o!erator -> t"at ma*es it a unary operator& 7 $!ass's o!erator -> fun$tion s"ou!d return a pointer to t"e o#1e$t t"at t"e arro operator s"ou!d a$tua!!y #e app!ied to& ,"is may #e a #it $onfusing, so an e(amp!e is in order& Suppose e "a%e a $!ass CustomString-ointer t"at a$ts as t"oug" it's a pointer to a C++ string o#1e$t& ,"en if e "a%e t"e fo!!o ing $ode.
CustomString-ointer myCustom-ointer# cout myCustom-ointer->length%& en0l#

,"is $ode is e'ui%a!ent to


CustomString-ointer myCustom-ointer# cout %myCustom-ointer$o!erator ->%&&->length%& en0l#

-n t"e first %ersion of t"e $ode, e treated t"e myCustom-ointer o#1e$t as t"oug" it as a rea! pointer #y using t"e arro operator to se!e$t t"e length fun$tion& ,"is $ode e(pands out into t o sma!!er steps. 1& ,"e CustomString-ointer's o!erator -> fun$tion is $a!!ed to determine "i$" pointer t"e arro s"ou!d #e app!ied to& 2& ,"e returned pointer t"en "as t"e -> operator app!ied to se!e$t t"e length fun$tion& ,"us "en riting t"e o!erator -> fun$tion, you simp!y need to return t"e pointer t"at t"e arro operator s"ou!d #e app!ied to& -f you're riting a $ustom iterator $!ass, for e(amp!e, t"is is pro#a#!y t"e e!ement #eing iterator o%er&

+ 1D +

$ist o& Overloada!le Operators ,"e fo!!o ing ta#!e !ists t"e most $ommon!y+used operators you're !ega!!y a!!o ed to o%er!oad in C++, a!ong it" any restri$tions a#out "o you s"ou!d define t"e operator&
=

7ssignment

*yClass5 o!erator =%const *yClass5 other&#

See t"e Handout #2B for detai!s&


+= -= *= /= S=
%etc$&

Compound assignment

*yClass5 o!erator +=%const *yClass5 other&#

/"en riting $ompound assignment operators, ma*e sure t"at you $orre$t!y "and!e 3se!f+$ompound+assignment&4 Mat"emati$a! operators const *yClass
o!erator + %const *yClass5 other& const# /rien0 const *yClass o!erator +%const OtherClass5 one" const *yClass5 two&#

+ - * / S

/"en o%er!oading arit"meti$ operators "en t"e parameter isn't of t"e same type as your $!ass, ma*e sure to define free fun$tions to $orre$t!y "and!e t"e parameter ordering&
-

)nary minus

const *yClass o!erator - %& const#

,"e unary minus operator is t"e minus operator in%o*ed "en riting $ode !i*e y = -8& -t's easy to forget to o%er!oad t"is one, so #e sure to *eep an eye out for it&
= == > >= J=

<e!ationa! operators

bool o!erator %const *yClass5 other& const# /rien0 bool o!erator %const *yClass5 one" const *yClass5 two&#

-f you're p!anning to use re!ationa! operators on!y for t"e S,L $ontainer $!asses, you 1ust need to o%er!oad t"e operator& Ot"er ise, you s"ou!d o%er!oad a!! si( so t"at users aren't surprised t"at one J= two is i!!ega! "i!e J%one == two& is defined&
12

G!ement Se!e$tion

Alem9y!e5 o!erator 12%const Tey9y!e5 Dey&# const Alem9y!e5 o!erator 12%const Tey9y!e5 Dey& const#

Most of t"e time you'!! need a const+o%er!oaded %ersion of t"e #ra$*et operator& 8orgetting to pro%ide one $an !ead to a rea! "eada$"e>
++ -J

-n$rementJ@e$rement Logi$a! not

:refi( %ersion. *yClass5 o!erator ++%&# :ostfi( %ersion. const *yClass o!erator ++%int 0ummy&#
bool o!erator J%& const#

/e didn't $o%er t"is operator in t"is "andout, #ut you s"ou!d #e a are t"at it e(ists&

+ 16 +

Overloadable Operators, contd.


*

:ointer dereferen$e

Alem9y!e5 o!erator *%& const#

/it" t"is fun$tion, you're a!!o ing your $!ass to a$t as t"oug" it's a pointer& ,"e return type s"ou!d #e a referen$e to t"e o#1e$t it's 3pointing4 at& ,"is is "o t"e S,L iterators and smart pointers or*& 2ote t"at t"is is t"e unary * operator and is not t"e same as t"e * mu!tip!i$ati%e operator&
->

:ointer+to+mem#er

-ointer9y!e o!erator ->%& const#

-f t"e '( is o%er!oaded for a $!ass, "ene%er you rite myClass->my*ember, it's e'ui%a!ent to myClass$o!erator ->%&->my*ember& 2ote t"at t"e fun$tion s"ou!d #e const e%en t"oug" t"e o#1e$t returned $an sti!! modify data& ,"is "as to do it" "o pointers $an !ega!!y #e used in C++& 8or more information, refer to t"e "andout on const&
>>

Stream operators

/rien0 ostream5 o!erator

%ostream5 out" const *yClass5 mc&#

/rien0 istream5 o!erator >> %istream5 in" *yClass5 mc&# %&

8un$tion Ca!!

See Handout #2F 5distri#uted on ,"ursday6

More to )*plore Operator o%er!oading is an enormous topi$ in C++ and t"ere's simp!y not enoug" spa$e to $o%er it a!! in t"is "andout& -f you're interested in some more ad%an$ed topi$s, $onsider reading into t"e fo!!o ing. 1& Overloaded new and delete. ?ou are a!!o ed to o%er!oad t"e new and 0elete operators, in $ase you ant to $"ange "o memory is a!!o$ated for your $!ass& 2ote t"at t"e o%er!oaded new and 0elete operators simp!y $"ange "o memory is a!!o$ated, not "at it means to rite new *yClass& O%er!oading new and 0elete is a $omp!i$ated tas* and re'uires a so!id understanding of "o C++ memory management or*s, so #e sure to $onsu!t a referen$e for detai!s& 2& Conversion &unctions. -n Handout #22, e $o%ered "o to rite $on%ersion $onstru$tors, fun$tions t"at $on%ert o#1e$ts of ot"er types into instan$es of your ne $!ass& Ho e%er, it's possi#!e to use operator o%er!oading to define an imp!i$it $on%ersion from o#1e$ts of your $!ass into o#1e$ts of ot"er types& ,"e synta( is o!erator 9y!e%&, "ere 9y!e is t"e data type to $on%ert your o#1e$t to& Many professiona! programmers ad%ise against $on%ersion fun$tions, so ma*e sure t"at t"ey're rea!!y t"e #est option #efore pro$eeding& B& Custom stream manipulators. ?ou $an a!so o%er!oad t"e and >> operators to define your o n $ustom stream manipu!ators& ,o rite a stream manipu!ator, simp!y define a ne $!ass t"at o%er!oads t"e or >> operators to modify t"e properties of a stream instead of riting a %a!ue&

+ 1F +

Practice Pro!lems Operator o%er!oading is 'uite diffi$u!t #e$ause your fun$tions must a$t as t"oug" t"ey're t"e #ui!t+in operators& Here are some pra$ti$e pro#!ems to get you used to o%er!oading operators. 1& -f you'%e o%er!oaded #ot" t"e prefi( and postfi( %ersions of t"e ++ operator for a $ertain $!ass, t"en "at does t"e $ode ++myClass e(pand into9 /"at a#out myClass++9 2& /"y is it #etter to imp!ement + in terms of += instead of += in terms of +9 B& G(p!ain "o it's possi#!e to define a!! of t"e re!ationa! operators in terms of & C& )sing t"e ?ational<umber $!ass from t"e $on%ersion $onstru$tor "andout as a starting point, define t"e re!ationa! operators 5 = == J= >= >6 for ?ational<umber& D& Ki%en a CString $!ass t"at stores a C string as char* theString, rite an o%er!oaded #ra$*et operator for CString& Ma*e sure it's const+$orre$t> 6& Consider t"e fo!!o ing definition of a S!an stru$t.
struct S!an ; int start" sto!# S!an%int begin" int en0& ) start%begin&" sto!%en0& ;B B# ,"e S!an stru$t a!!o s us to define t"e range of e!ements from Lstart, sto!6 as a sing!e %aria#!e& Ki%en t"is definition of S!an and assuming start and sto! are #ot" non+negati%e, pro%ide anot"er #ra$*et operator for CString t"at a$$epts a S!an #y referen$e+to+const and returns anot"er CString e'ua! to t"e su#string of t"e initia! CString from start to sto!&

F& /"i!e !ega!, is it a good idea to pro%ide t"e operator o%er!oad suggested in t"e pre%ious pro#!em9 /"y or "y not9

+ 1H +

Anda mungkin juga menyukai