Sie sind auf Seite 1von 7

6.

096 Introduction to C++ Massachusetts Institute of Technology

January 24th, 2011 John Marrero

Lecture 9 Notes: Advanced Topics I

Templates

e ha!e seen that functions can ta"e argu#ents of s$ecific ty$es and ha!e a s$ecific return ty$e. e no% consider templates, %hich allo% us to %or" %ith generic types. Through te#$lates, rather than re$eating function code for each ne% ty$e %e %ish to acco##odate, %e can create functions that are ca$a&le of using the sa#e code for different ty$es. 'or e(a#$le) 1 int sum(const int x, const int y) { 2 return x + y; 3 } 'or this function to %or" %ith dou&les, it #ust &e #odified to the follo%ing) 1 double sum (const double x, const double y) { 2 return x + y; 3 } 'or a si#$le function such as this, it #ay &e a s#all #atter to *ust #a"e the change as sho%n, &ut if the code %ere #uch #ore co#$licated, co$ying the entire function for each ne% ty$e can +uic"ly &eco#e $ro&le#atic. To o!erco#e this %e re%rite sum as a function te#$late. The for#at for declaring a function te#$late is) template <class identifier> function_declaration; or template <typename identifier> function_declaration; ,oth for#s are e+ui!alent to one another, regardless of %hat ty$e identifier ends u$ &eing. can then use identifier to re$lace all occurrences of the ty$e %e %ish to generali-e. .o, %e re%rite our sum function) 1 template <typename T> 2 T sum(const T a, const T b) { 3 return a + b; } /o%, %hen sum is called, it is called %ith a $articular ty$e, %hich %ill re$lace all Ts in the code. To in!o"e a function te#$late, %e use) function_name <type> (parameters); 0ere is an e(a#$le main function using the a&o!e sum function te#$late) 1 int main() { 2 cout << sum<int>(1, 2) << endl; 3 cout << sum<!loat>(1"21, 2" 3) << endl; return #; $ } This $rogra# $rints out 3 and 3"% on se$arate lines. e

The identifier can &e used in any %ay inside the function te#$late, as long as the code #a"es sense after identifier is re$laced %ith so#e ty$e. It is also $ossi&le to in!o"e a function te#$late %ithout gi!ing an e($licit ty$e, in cases %here the generic ty$e identifier is used as the ty$e for a $ara#eter for the function. In the a&o!e e(a#$le, the follo%ing %ould also ha!e &een !alid) 1 int main() { 2 cout << sum(1, 2) << endl; 3 cout << sum(1"21, 2" 3) << endl; return #; $ } Te#$lates can also s$ecify #ore than one ty$e $ara#eter. 'or e(a#$le) 1 2 3 $ % ) * + 1# 11 12 &include <iostream> usin' namespace std; template <typename T, typename (> ( sum(const T a, const ( b) { return a + b; } int main() { cout << sum<int, !loat>(1, 2"$) << endl; return #; }

This $rogra# $rints out 3"$. In this case %e can also call su# &y %riting sum(1, 2"$). Class te#$lates are also $ossi&le, in #uch the sa#e %ay %e ha!e %ritten function te#$lates) 1 2 3 $ % ) * + 1# 11 12 13 1 1$ 1% 1) 1* &include <iostream> usin' namespace std; template <typename T> class ,oint { pri-ate. T x, y; public. ,oint(const T u, const T -) . x(u), y(-) {} T 'et/() { return x; } T 'et0() { return y; } }; int main() { ,oint<!loat> !point(2"$, 3"$); cout << !point"'et/() << 1, 1 << !point"'et0() << endl; return #; }

The $rogra# $rints out 2"$, 3"$. To declare #e#&er functions e(ternally, %e use the follo%ing synta() template <typename T> T classname<T>..!unction2name() .o, for e(a#$le, get1 could ha!e &een declared in the follo%ing %ay)

template <typename T> T ,oint<T>..'et/() { return x; } assu#ing a $rototy$e of T 'et/(); inside the class definition. e can also define different i#$le#entations for a single te#$late &y using template specialization. Consider the follo%ing e(a#$le) 1 2 3 $ % ) * + 1# 11 12 13 1 1$ 1% 1) 1* 1+ 2# 21 22 23 2 2$ 2% 2) 2* 2+ &include <iostream> &include <cctype> usin' namespace std; template <typename T> class 3ontainer { pri-ate. T elt; public. 3ontainer(const T ar') . elt(ar') {} T inc() { return elt+1; } }; template <> class 3ontainer <c4ar> { pri-ate. c4ar elt; public. 3ontainer(const c4ar ar') . elt(ar') {} c4ar uppercase() { return toupper(elt); } }; int main() { 3ontainer<int> icont($); 3ontainer<c4ar> ccont(5r5); cout << icont"inc() << endl; cout << ccont"uppercase() << endl; return #; }

This $rogra# $rints out % and 6 on se$arate lines. 0ere, the class 3ontainer is gi!en t%o i#$le#entations) a generic one and one s$ecifically tailored to the c4ar ty$e. /otice the synta( at lines 14 and 12 %hen declaring a s$eciali-ation. 'inally, it is $ossi&le to $ara#etri-e te#$lates on regular ty$es) 1 2 3 &include <iostream> usin' namespace std;

template <typename T, int 7> $ class 8rray3ontainer { % pri-ate. ) T elts97:; * public. + T set(const int i, const T -al) { elts9i: ; -al; } 1# T 'et(const int i) { return elts9i:; } 11 }; 12 13 int main() { 1 8rray3ontainer <int, $> intac; 1$ 8rray3ontainer <!loat, 1#> !loatac; 1% intac"set(2, 3); 1) !loatac"set(3, 3"$); 1* cout << intac"'et(2) << endl; 1+ cout << !loatac"'et(3) << endl;

2# 21 }

return #;

This $rogra# $rints out 3 and 3"$ on se$arate lines. 0ere, one instance of the 3rrayContainer class %or"s on a 24ele#ent array of ints %hereas the other instance %or"s on a 104ele#ent array of !loats. 5efault !alues can &e set for te#$late $ara#eters. 'or e(a#$le, the $re!ious te#$late definition could ha!e &een) template <typename T;int, int 7;$> class 8rray3ontainer { """ } and %e could ha!e created an 8rray3ontainer using the default $ara#eters &y %riting) 8rray3ontainer<> identifier; 2 Standard Template Library

6art of the C++ .tandard 7i&rary, the Standard Template Library 8.T79 contains #any useful container classes and algorith#s. 3s you #ight i#agine, these !arious $arts of the li&rary are %ritten using te#$lates and so are generic in ty$e. The containers found in the .T7 are lists, #a$s, +ueues, sets, stac"s, and !ectors. The algorith#s include se+uence o$erations, sorts, searches, #erges, hea$ o$erations, and #in:#a( o$erations. e %ill e($lore ho% to use so#e of these through e(a#$le here) 1 2 3 &include <iostream> &include <set> &include <al'orit4m> usin' namespace std;

$ % int main() { ) set<int> iset; * iset"insert($); + iset"insert(+); 1# iset"insert(1); 11 iset"insert(*); 12 iset"insert(3); 13 1 cout << 1iset contains.1; 1$ set<int>..iterator it; 1% !or(it;iset"be'in(); it <; iset"end(); it++) 1) cout << 1 1 << =it; 1* cout << endl; 1+ 2# int searc4>or; 21 cin >> searc4>or; 22 i!(binary2searc4(iset"be'in(), iset"end(), searc4>or)) 23 cout << 1>ound 1 << searc4>or << endl; 2 else 2$ cout << 1?id not !ind 1 << searc4>or << endl; 2% 2) return #; 2* } In this e(a#$le, %e create an integer set and insert se!eral integers into it. e then create an iterator corres$onding to the set at lines 14 and 12. 3n iterator is &asically a $ointer that $ro!ides a !ie% of the set. 8Most of the other containers also $ro!ide iterators.9 ,y using this iterator, %e dis$lay all the ele#ents in the set and $rint out iset contains. 1 3 $ * +. /ote that the set auto#atically sorts its o%n ite#s. 'inally, %e as" the user for an integer, search for that integer in the set, and dis$lay the result.

0ere is another e(a#$le) 1 2 3 &include <iostream> &include <al'orit4m> usin' namespace std;

-oid print8rray(const int arr9:, const int len) { $ !or(int i;#; i < len; i++) % cout << 1 1 << arr9i:; ) cout << endl; * } + 1# int main() { 11 int a9: ; {$, ), 2, 1, , 3, %}; 12 13 sort(a, a+)); 1 print8rray(a, )); 1$ rotate(a,a+3,a+)); 1% print8rray(a, )); 1) re-erse(a, a+)); 1* print8rray(a, )); 1+ 2# return #; 21 } This $rogra# $rints out) 1 2 3 $ % ) $ % ) 1 2 3 3 2 1 ) % $ The .T7 has #any, #any #ore containers and algorith#s that you can use. ;ead #ore at htt$)::%%%.c$lus$lus.co#:reference:stl and htt$)::%%%.c$lus$lus.co#:reference:algorith#:. 3 Operator Overloading

e ha!e &een using o$erators on $ri#iti!es, &ut so#eti#es it #a"es sense to use the# on user4defined dataty$es. 'or instance, consider the follo%ing struct) struct (@3urrency { int dollars; int cents; }; 6erha$s %e %ould li"e to add t%o (@3urrency o&*ects together and get a ne% one as a result, *ust li"e in nor#al addition) (@3urrency a ; {2, $#}; (@3urrency b ; {1, )$}; (@3urrency c ; a + b; This of course gi!es a co#$iler error, &ut %e can define &eha!ior that our dataty$e should ha!e %hen used %ith the addition o$erator &y o!erloading the addition o$erator. This can &e done either inside the class as $art of its definition 8the addition fro# the $oint of !ie% of the o&*ect on the left side of the +9) 1 2 3 (@3urrency operator+(const (@3urrency o) { (@3urrency tmp ; {#, #}; tmp"cents ; cents + o"cents; tmp"dollars ; dollars + o"dollars;

$ % ) * + 1# 11 12 }

i!(tmp"cents >; 1##) { tmp"dollars +; 1; tmp"cents A; 1##; } return tmp;

or outside the class as a function inde$endent of the class 8the addition fro# the $oint of !ie% of the +9) 1 2 3 (@3urrency operator+(const (@3urrency m, const (@3urrency o) { (@3urrency tmp ; {#, #}; tmp"cents ; m"cents + o"cents; tmp"dollars ; m"dollars + o"dollars; i!(tmp"cents >; 1##) { tmp"dollars +; 1; tmp"cents A; 1##; } return tmp;

$ % ) * + 1# 11 12 }

.i#ilarly, %e can o!erload the << o$erator to dis$lay the result) 1 ostreamB operator<<(ostream Boutput, const (@3urrency Bo) 2 { 3 output << 1C1 << o"dollars << 1"1 << o"cents; return output; $ } 3ssu#ing the a&o!e definitions, %e can run the follo%ing $rogra#) 1 int main() { 2 (@3urrency a 3 (@3urrency b (@3urrency c $ cout << c << % return #; ) } ; {2, $#}; ; {1, )$}; ; a + b; endl;

and get the $rintout C "2$. The list of o!erloada&le o$erators) + ; << 9: A ;; >> () = < <<; , D > >>; A>= +; <; B A> A; >; G neI =; < F neI9: D; E <; BB B; G; delete E; ++ FF F; H delete9: AA

MIT OpenCourseWare http://ocw.mit.edu

6.096 Introduction to C++


January (IAP) 2011

For information about citing these materials or our Terms of Use, visit: http://ocw.mit.edu/terms.

Das könnte Ihnen auch gefallen