You are on page 1of 6

SECTION [31]: Container classes and templates

[31.1] How can I make a perl-like associative array in C++?


Use the standard class template map!ey"#al$%
&incl'de strin($
&incl'de map$
&incl'de iostream$
'sin( namespace std)
main*+
,
mapstrin("int"lessstrin($ $ a(e) -- a(e is a map .rom strin( to int
a(e[/0red/] 1 23) -- 0red is 23 years old
a(e[/4arney/] 1 35) -- 4arney is 35
i. *todayIs0reds4irthday*++ -- 6n 0red7s 8irthday"
++ a(e[/0red/]) -- increment 0red7s a(e
co't /0red is / a(e[/0red/] / years old9n/)
:
1111111111111111111111111111111111111111111111
111111111111
[31.3] How can I build a <a!orite container" o ob#ects o di$erent
t%pes&
;o' can7t" 8't yo' can .ake it pretty well. In C-C++ all arrays are
homo(eneo's *i.e." the elements are all the same type+. However" with an
e<tra layer o. indirection yo' can (ive the appearance o. a hetero(eneo's
container *a hetero(eneo's container is a container where the contained
o8=ects are o.
di>erent types+.
T'ere are two cases wit' 'etero(eneous containers.
?he @rst case occ'rs when all o8=ects yo' want to store in a container are
p'8licly derived .rom a common 8ase class. ;o' can then declare-de@ne
yo'r container to hold pointers to the 8ase class. ;o' indirectly store a
derived class o8=ect in a container 8y storin( the o8=ect7s address as an
element in the container. ;o' can then access o8=ects in the container
indirectly thro'(h the pointers *en=oyin( polymorphic 8ehavior+. I. yo' need
to know the e<act type o. the o8=ect in the container yo' can 'se
dynamicAcast$ or typeid*+. ;o'7ll pro8a8ly need the #irt'al Constr'ctor
Idiom[3B.C] to copy a container o. disparate o8=ect types. ?he downside o.
this approach is that it makes memory mana(ement a little more
pro8lematic *who /owns/ the pointed-to o8=ects? i. yo' delete these pointed-
to o8=ects when yo' destroy the container" how can yo' ('arantee that no
one else has a copy o. one o. these pointers? i. yo' don7t delete these
pointed-to o8=ects when yo' destroy the container" how can yo' 8e s're that
someone else will event'ally do the deletein(?+. It also makes copyin( the
container more comple< *may act'ally 8reak the container7s copyin(
.'nctions since yo' don7t want to copy the pointers" at least not when the
container /owns/ the pointed-to o8=ects+.
?he second case occ'rs when the o8=ect types are dis=oint -- they do not
share a common 8ase class. ?he approach here is to 'se a handle class. ?he
container is a container o. handle o8=ects *8y val'e or 8y pointer" yo'r
choice) 8y val'e is easier+. Dach handle o8=ect knows how to /hold on to/
*i.e. "maintain a pointer to+ one o. the o8=ects yo' want to p't in the
container. ;o' can 'se either a sin(le handle class with several di>erent
types o. pointers as instance data" or a hierarchy o. handle classes that
shadow the vario's types yo' wish to contain *reE'ires the container 8e o.
handle 8ase class pointers+. ?he downside o. this approach is that it opens
'p the handle class*es+ to maintenance every time yo' chan(e the set o.
types that can 8e contained. ?he 8ene@t is that yo' can 'se the handle
class*es+ to encaps'late most o. the '(liness o. memory mana(ement and
o8=ect li.etime. ?h's 'sin( handle o8=ects may 8e 8ene@cial even in the @rst
case.
1111111111111111111111111111111111111111111111
111111111111
[31.3] How can I insert-access-chan(e elements .rom a linked
list-hashta8le-etc?
I7ll 'se an /insertin( into a linked list/ as a prototypical e<ample. It7s easy to
allow insertion at the head and tail o. the list" 8't limitin( o'rselves to these
wo'ld prod'ce a li8rary that is too weak *a weak li8rary is almost worse
than no li8rary+.
?his answer will 8e a lot to swallow .or novice C++7ers" so I7ll (ive a co'ple
o. options. ?he @rst option is easiest) the second and third are 8etter.
1. Dmpower the Fist with a /c'rrent location"/ and mem8er .'nctions s'ch
as advance*+" 8ack'p*+" atDnd*+" at4e(in*+" (etC'rrDlem*+"
setC'rrDlem*Dlem+" insertDlem*Dlem+" and removeDlem*+. Gltho'(h this
works in small e<amples" the notion o. a c'rrent position makes it
di>ic'lt to access elements at two or more positions within the list *e.(."
/.or all pairs <"y do the .ollowin(.../+.
3. Hemove the a8ove mem8er .'nctions .rom Fist itsel." and move them to a
separate class" FistIosition. FistIosition wo'ld act as a /c'rrent
position/ within a list. ?his allows m'ltiple positions within the same list.
FistIosition wo'ld 8e a .riend[12] o. class Fist" so Fist can hide its
innards .rom the o'tside world *else the innards o. Fist wo'ld have to 8e
p'8liciJed via p'8lic mem8er .'nctions in Fist+. Kote% FistIosition can
'se operator overloadin( .or thin(s like advance*+ and 8ack'p*+" since
operator overloadin( is syntactic s'(ar .or normal mem8er .'nctions.
3. Consider the entire iteration as an atomic event" and create a class
template to em8odies this event. ?his enhances per.ormance 8y allowin(
the p'8lic access mem8er .'nctions *which may 8e virt'al [3B] .'nctions+
to 8e avoided d'rin( the inner loop. Un.ort'nately yo' (et e<tra o8=ect
code in the application" since templates (ain speed 8y d'plicatin( code.
0or more" see [!oeni(" /?emplates as inter.aces"/ L66I" 2" C *Mept N1+]"
and [ Mtro'str'p" /?he C++ Iro(rammin( Fan('a(e Mecond Ddition"/
'nder /Comparator/].
1111111111111111111111111111111111111111111111
111111111111
[31.2] )'at*s t'e idea be'ind templates&
G template is a cookie-c'tter that speci@es how to c't cookies that all look
pretty m'ch the same *altho'(h the cookies can 8e made o. vario's kinds o.
do'(h" they7ll all have the same 8asic shape+. In the same way" a class
template is a cookie c'tter .or a description o. how to 8'ild a .amily o.
classes that all look 8asically the same" and a .'nction template descri8es
how to 8'ild a .amily o. similar lookin( .'nctions.
Class templates are o.ten 'sed to 8'ild type sa.e containers *altho'(h this
only scratches the s'r.ace .or how they can 8e 'sed+.
1111111111111111111111111111111111111111111111
111111111111
[31.C] Ohat7s the synta< - semantics .or a /.'nction template/?
Consider this .'nction that swaps its two inte(er ar('ments%
void swap*intP <" intP y+
,
int tmp 1 <)
< 1 y)
y 1 tmp)
:
I. we also had to swap Qoats" lon(s" Mtrin(s" Mets" and 0ile Mystems" we7d (et
pretty tired o. codin( lines that look almost identical e<cept .or the type.
Rindless repetition is an ideal =o8 .or a comp'ter" hence a .'nction template%
templateclass ?$
void swap*?P <" ?P y+
,
? tmp 1 <)
< 1 y)
y 1 tmp)
:
Dvery time we 'sed swap*+ with a (iven pair o. types" the compiler will (o to
the a8ove de@nition and will create yet another /template .'nction/ as an
instantiation o. the a8ove. D.(."
main*+
,
int i"=) -S...S- swap*i"=+) -- Instantiates a swap .or int
Qoat a"8) -S...S- swap*a"8+) -- Instantiates a swap .or Qoat
char c"d) -S...S- swap*c"d+) -- Instantiates a swap .or char
Mtrin( s"t) -S...S- swap*s"t+) -- Instantiates a swap .or Mtrin(
:
Kote% G /template .'nction/ is the instantiation o. a /.'nction template/.
1111111111111111111111111111111111111111111111
11111111111
[31.T] Ohat7s the synta< - semantics .or a /class template/?
Consider a container class Grray that acts like an array o. inte(ers%
-- ?his wo'ld (o into a header @le s'ch as /Grray.h/
class Grray ,
p'8lic%
Grray*int len11B+ % lenA*len+" dataA*new int[len]+ , :
UGrray*+ , delete [] dataA) :
int len*+ const , ret'rn lenA) :
const intP operator[]*int i+ const , ret'rn dataA[check*i+]) :
intP operator[]*int i+ , ret'rn dataA[check*i+]) :
Grray*const GrrayP+)
GrrayP operator1 *const GrrayP+)
private%
int lenA)
intS dataA)
int check*int i+ const
, i. *i B VV i $1 lenA+ throw 4o'nds#iol*/Grray/" i" lenA+)
ret'rn i) :
:)
L'st as with swap*+ a8ove" repeatin( the a8ove over and over .or Grray o.
Qoat" o. char" o. Mtrin(" o. Grray-o.-Mtrin(" etc" will 8ecome tedio's.
-- ?his wo'ld (o into a header @le s'ch as /Grray.h/
templateclass ?$
class Grray ,
p'8lic%
Grray*int len11B+ % lenA*len+" dataA*new ?[len]+ , :
UGrray*+ , delete [] dataA) :
int len*+ const , ret'rn lenA) :
const ?P operator[]*int i+ const , ret'rn dataA[check*i+]) :
?P operator[]*int i+ , ret'rn dataA[check*i+]) :
Grray*const Grray?$P+)
Grray?$P operator1 *const Grray?$P+)
private%
int lenA)
?S dataA)
int check*int i+ const
, i. *i B VV i $1 lenA+ throw 4o'nds#iol*/Grray/" i" lenA+)
ret'rn i) :
:)
Unlike template .'nctions" template classes *instantiations o. class
templates+ need to 8e e<plicit a8o't the parameters over which they are
instantiatin(%
main*+
,
Grrayint$ ai)
GrrayQoat$ a.)
GrraycharS$ ac)
GrrayMtrin($ as)
Grray Grrayint$ $ aai)
:
Kote the space 8etween the two $7s in the last e<ample. Oitho't this space"
the compiler wo'ld see a $$ *ri(ht-shi.t+ token instead o. two $7s.
1111111111111111111111111111111111111111111111
111111111111
[31.5] Ohat is a /parameteriJed type/?
Gnother way to say" /class templates./
G parameteriJed type is a type that is parameteriJed over another type or
some val'e. Fistint$ is a type *Fist+ parameteriJed over another type *int+.
1111111111111111111111111111111111111111111111
111111111111
[31.W] Ohat is /(enericity/?
;et another way to say" /class templates./
Kot to 8e con.'sed with /(enerality/ *which ='st means avoidin( sol'tions
which are overly speci@c+" /(enericity/ means class templates.
1111111111111111111111111111111111111111111111
111111111111

You might also like