Kurz C++ (5.) Vφtßm Vßs na dalÜφm pokraΦovßnφ naÜeho kurzu o C++. Dnes si povφme n∞co o funkcφch. ZßkladyFunkce nßm umo₧≥ujφ napsat k≤d, kter² provßdφ n∞jakou operaci, pouze jednou, a pak se na n∞j odkazovat z jakΘhokoli mφsta v programu (programßtorsky se tomu °φkß "zavolat funkci"). M∙₧eme tak provßd∞t stejnou Φinnost na r∙zn²ch mφstech v programu ani₧ bychom poka₧dΘ museli napsat stejn² k≤d. Funkce takΘ vnßÜejφ do k≤du modularitu a °ßd a d∞lajφ program p°ehledn∞jÜφm. Funkce m∙₧e zφskat od volajφcφho programu n∞jakΘ informace (°φkß se jim "parametry funkce"), a m∙₧e mu n∞jakou informaci vrßtit (to je "nßvratovß hodnota"). Jak parametry, tak nßvratovß hodnota mohou b²t jakΘhokoli datovΘho typu. P°ed pou₧itφm funkcφ si musφme ujasnit pojmy deklarace a definice.
Deklaracφ °φkßme kompilßtoru, ₧e n∞kde dßle v programu volßme takovou
funkci, a dßvßme mu k dispozici p°φsluÜnΘ ·daje o nφ (jmΘno, seznam
parametr∙, typ nßvratovΘ hodnoty). P°φklad dvou deklaracφ:
Na prvnφm mφst∞ je typ nßvratovΘ hodnoty, v naÜem p°φpad∞ funkce min vracφ celΘ Φφslo, funkce vypisCopyright nevracφ v∙bec nic - to je v²znam klφΦovΘho slova void. Dßle nßsleduje jmΘno funkce (min, vypisCopyright) a pak v kulat²ch zßvorkßch seznam parametr∙ (uvßdφ se datov² typ a jmΘno parametru - funkce min mß tedy dva celoΦφselnΘ parametry (a, b), funkce vypisCopyright nemß ₧ßdn² parametr. TakovΘmu °ßdku se °φkß "hlaviΦka funkce". Poznßmka: V n∞kter²ch programech se m∙₧ete setkat s deklaracφ, kterß vypadß nßsledovn∞:
tedy mφsto prßzdnΘho seznamu parametr∙ je klφΦovΘ slovo void. Je to naprosto totΘ₧ jako p°φklad vypisCopyright v²Üe (funkce bez parametr∙), ale v jazyce C (p°edch∙dci jazyka C++). VÜimn∞te si, ₧e deklaracφ jeÜt∞ neuvßdφme, co vlastn∞ bude funkce provßd∞t. To kompilßtoru °φkßme a₧ definicφ:
Definice tedy zaΦφnß op∞tovn²m uvedenφm hlaviΦky, ale mφsto st°ednφku na konci ji₧ pφÜeme k≤d, kter² se ve funkci vykonßvß, uzav°en do slo₧en²ch zßvorek ("t∞lo" funkce). V p°φkladu jsme pou₧ili dalÜφ klφΦovΘ slovo jazyka C++, a sice p°φkaz return. Tφmto p°φkazem °φkßme: tady skonΦi provßd∞nφ funkce, vra¥ hodnotu a p°edej °φzenφ nad°azenΘmu programu (kter² funkci zavolal). Prob∞hne-li p°φkaz return, dalÜφ p°φkazy, kterΘ za nφm mohou nßsledovat, se neprovedou. Nßvrat do nad°azenΘho programu takΘ probφhß samovoln∞ na konci funkce. Pokud funkce nic nevracφ, return tam ani nemusφ b²t (viz funkci vypisCopyright). V opaΦnΘm p°φpad∞ je pou₧itφ return i s n∞jakou nßvratovou hodnotu povinnΘ (funkce min). Pou₧φtφ funkce v programu vypadß takto:
Prom∞nnΘ v²sledek jsme p°i°adili nßvratovou hodnotu funkce
min. Funkci
m∙₧eme pou₧φt na vÜech mφstech, kde kompilßtor oΦekßvß v²raz stejnΘho
datovΘho typu, jako je jejφ nßvratovß hodnota, p°iΦem₧ funguje implicitnφ
i explicitnφ konverze. Funkci s nßvratov²m typem void m∙₧eme pou₧φvat jako
p°φkaz, (v jazyce Pascal existuje pom∞rn∞ v²sti₧n² termφn "procedura") ale
nesmφme zapomenout na zßvorky. Vlastn∞ jakoukoli funkci m∙₧eme pou₧φvat
jako proceduru, tedy ignorujeme nßvratovou hodnotu. V minulΘm dφle jsme
mluvili o funkci strcpy. Ta je deklarovßna takto:
Funkce spojφ oba °et∞zce do °et∞zce str1, kter² pak vracφ. Nßs
pravd∞podobn∞ nezajφmß nßvratovß hodnota, proto₧e °et∞zec
str1 mßme n∞kde
deklarovan², tak₧e ji m∙₧eme ignorovat a zavolat funkci takto:
Dßle si vÜimn∞te, ₧e funkci m∙₧eme deklarovat i definovat kdekoli v programu (ale mimo jinou funkci - deklarovat nap°φklad ve funkci main jinou funkci by neÜlo).
Poznßmka: z tohoto p°φkladu je vid∞t, ₧e veÜker² k≤d programu je uzav°en v n∞jakΘ funkci, mimo ni nem∙₧ete psßt k≤d, pouze deklarovat prom∞nnΘ a konstanty. Tak₧e tvrzenφm "program volß funkci" jsem se dopustil malΘ nep°esnosti (z d∙vodu jednoduchosti v²kladu): ve skuteΦnosti je v₧dy funkce zavolßna jinou funkci (a₧ na funkci main, kterß je zavolßna operaΦnφm systΘmem). V²Üe uveden² p°φklad na pou₧φvßnφ funkce je mo₧nß trochu zarß₧ejφcφ,
proto₧e chybφ deklarace funkce vypisCopyright. Deklarace funkcφ jsou ve
skuteΦnosti nepovinnΘ. Pokud funkci definujeme p°ed tφm, ne₧ ji poprvΘ
zavolßme, tak deklarace je vlastn∞ zbyteΦnß, proto₧e v okam₧iku zavolßni
funkce kompilßtor ji₧ mß vÜechny ·daje o nφ k dispozici. Kdybychom
posunuli funkci min p°ed funkci
main, mohli bychom vynechat i jejφ
deklaraci. NicmΘn∞ existujφ i p°φpady, kdy se bez deklaracφ neobejdeme.
Typick²m p°φkladem jsou dv∞ funkce, z nich₧ ka₧dß volß tou druhou:
Pokusφte-li se zkompilovat tento program, kompilßtor ohlßsφ chybu ve funkci a na °ßdku b(), proto₧e o funkci b zatφm nevφ v∙bec nic (postupuje shora dol∙). Poznßmka: pokud Vßm nenφ jasn² v²znam parametru stop, ten tam je pouze kv∙li tomu, aby vzßjemnΘ volßnφ funkcφ a a b v∙bec skonΦilo. Jinak by a stßle volala b, nßsledn∞ b volala a a nikdy by to neskonΦilo (tedy ano: "program zp∙sobil neplatnou operaci a bude ukonΦen", ale to asi nechcete). Aby nßm p°φklad v²Üe fungoval, musφme ho vylepÜit o deklaraci funkce b
p°ed funkcφ a:
TakovΘ p°φpady, kdy budete pot°ebovat deklarace, ovÜem nejsou p°φliÜ ΦastΘ, tak₧e se deklaracemi nemusφte obt∞₧ovat. StaΦφ, kdy₧ budete v∞d∞t, ₧e existujφ.
P°edßvßnφ parametr∙P°edstavte si, ₧e byste pot°ebovali funkci poΦφtajφcφ aritmetick² a
geometrick² pr∙m∞r (ob∞ najednou). To by znamenalo, ₧e funkce bude muset
vracet dv∞ hodnoty, a p°itom mßme k dispozici pouze jednu nßvratovou
hodnotu. Nabφzφ se mo₧nost pou₧φt k vracenφ v²sledk∙ parametry funkce.
Deklarace funkce by vypadala takto:
Mß tedy 2 vstupnφ parametry (Φφsla a, b), a dva v²stupnφ (do parametru
aritm budeme uklßdat spoΦten² aritmetick² pr∙m∞r, do
geom geometrick²):
Pokusφte-li se funkci pou₧φt, zjistφte, ₧e se vypisujφ n∞jakΘ nesmyslnΘ
hodnoty (a takΘ dostanete p°i p°ekladu upozorn∞nφ ₧e pou₧φvßte
neinicializovanΘ prom∞nnΘ aritm a
geom):
Je to tφm, ₧e existujφ dva zp∙soby p°edßvßnφ parametr∙: hodnotou a
odkazem. P°edßvßnφ odkazem se pou₧φvß standardn∞, a znamenß to, ₧e hodnoty
parametr∙ se zkopφrujφ a funkci se p°edajφ prßv∞ kopie. Tφm pßdem jakΘkoli
zm∞ny, kterΘ funkce provede, ₧e ve skuteΦnosti provedou na kopiφch, kterΘ
se p°i nßvratu zahazujφ. DalÜφ mo₧nostφ je p°edßvßnφ odkazem. V tomto
p°φpad∞ se funkci p°edajφ odkazy na parametry, tak₧e se veÜkerΘ zm∞ny do
hodnot parametr∙ promφtnou. U parametr∙ aritm a
geom pot°ebujeme tedy
p°edßvßnφ odkazem, to se udßvß operßtorem & (naz²vß se operßtor reference)
u t∞chto dvou parametr∙:
P°et∞₧ovßnφ funkcφFunkce min, kterou jsme si napsali, je pom∞rn∞ u₧iteΦnß a mo₧nß se Vßm
bude hodit i v dalÜφm programovßnφ. Mß ale jednu nev²hodu: umφ poΦφtat
nejmenÜφ hodnotu jen pro celß Φφsla. Chceme-li funkce
min i pro datov² typ
double, char atd., musφme si je napsat. Ve starΘm C muselo jmΘno funkce
b²t unikßtnφ, z Φeho₧ vypl²vß, ₧e nap°. funkce min pro
double by se
vlastn∞ nemohla jmenovat min, ale t°eba min_double. C++ je vysp∞lejÜφ a
tak v n∞m existuje mechanismus, kter² umo₧≥uje deklarovat vφce funkcφ se
stejn²m jmΘnem - je to p°et∞₧ovßnφ funkcφ (angl. function overloading),
nap°φklad:
Spustφte-li tento program, vypφÜe se nejd°φv 1, pak 1.5. Kompilßtor
poznal jakou funkci chceme volat podle typ∙ parametr∙. Prav∞ takhle to
funguje - dv∞ funkce se stejn²m jmΘnem se musφ liÜit alespo≥ typem jednoho
parametru. Nenφ mo₧nΘ p°et∞₧ovat funkce pouze na zßklad∞ rozdφlnΘho typu
nßvratovΘ hodnoty. P°edstavte si tento p°φklad:
Kdy₧ volßte funkci min jako proceduru, kompilßtor by nev∞d∞l, kterou funkci zavolat: tu bez parametru, nebo tu vracejφcφ int. Inline funkceKa₧dΘ volßnφ funkce spot°ebuje n∞jak² Φas procesoru. Nenφ to moc, ale
volßte-li funkci Φasto (nap°φklad v n∞jakΘm cyklu) a zßle₧φ-li na ka₧dΘm
taktu, m∙₧e to b²t poznat. Prßv∞ u takov²ch funkcφ m∙₧e b²t v²hodnΘ je
definovat jako inline. To znamenß, ₧e funkce se nezavolß, ale celΘ jejφ
t∞lo se vlo₧φ na mφsto, odkud ji volßme (inline
funkce fungujφ prakticky stejn∞ jako makra). Re₧ie spojenß se zavolßnφm
odpadne a program tak pob∞₧φ rychleji:
Pozor, funkci deklaruje jako inline pouze tehdy, kdy₧ mßte jistotu, ₧e to pot°ebujete. V p°evß₧nΘ v∞tÜin∞ p°φpad∙ to pot°ebovat nebudete, a program se nezrychlφ, ale bude vetÜφ. P°φkladNa zßv∞r tohoto dφlu si ukß₧eme rozsßhlejÜφ p°φklad. Bude se jednat o
program poΦφtajφcφ, kolika zp∙soby je mo₧no vybrat ze skupiny n prvk∙
skupinu k prkv∙, bez opakovßnφ (poΦet k-Φlenn²ch variacφ bez opakovßnφ z n
prvk∙). Nap°φklad je-li n = 4 a k = 2 jednß se o poΦet mo₧n²ch v²b∞r∙ dvou
prvk∙ ze cty°, p°iΦem₧ zßle₧φ na po°adφ - (a,b) je n∞co jinΘho ne₧ (b,a):
Vybaveni t∞mito znalostmi se m∙₧eme pustit do prßce: nejd°φv budeme
pot°ebovat p°eΦφst parametry z p°φkazovΘ °ßdky a p°ipravit je pro v²poΦet:
Na konci programu vypisujeme v²sledek funkcφ variace, kterß spoΦte
po₧adovan² poΦet variacφ na zßklad∞ parametr∙ n a k. Tuto funkci si musφme
definovat (p°ed funkci main, abychom nemuseli psßt i deklaraci), podle
matematickΘho vzorce:
Ve funkci variace pou₧φvßme funkci faktorial, tak₧e ji p°idßme:
A to je vÜechno. ZajφmavΘ je snad jen to, ₧e funkce variace a faktorißl dostßvajφ parametry typu unsigned int (celΘ Φφslo bez znamΘnka) a takΘ takovou hodnotu vracejφ. To je v po°ßdku, variaci ani faktorißl ze zßporn²ch Φφsel poΦφtat nelze. Ale p°i Φtenφ parametr∙ z p°φkazovΘ °ßdky ve funkci main pou₧φvßme prom∞nnΘ typu int, abychom mohli zachytit pokus u₧ivatele o zadßnφ zßporn²ch Φφsel (kdybychom mφsto int pou₧ili i tady unsigned int doÜlo by p°i zadßnφ zßpornΘho Φφsla k p°eteΦenφ a nap°. mφsto Φφsla -1 by se do prom∞nnΘ ulo₧ilo 4294967295).
D∞kuji za pozornost a t∞Üφm se na dalÜφ dφl. |
|
⌐ 2001 Vogel Publishing, design by ET NETERA