PROTOTIPI
Primer programa ------> PROTYPE1.CPP
Oglejmo si ponazoritev prototipa v datoteki PROTYPE1.CPP. Oporaba prototipov v C++ je enaka kot pri ANSI-C.
Prototip je omejen model bolj zapletene entitete, ki jo izpopolnimo kasneje . V našem primeru je prototip funkcije v vrstici 4. Prototip podaja model vmesnika, kako in s kakšnimi parametri bomo klicali napovedano funkcijo. Vsak klic funkcije do_stuff() mora imeti natančno tri parametre, sicer bo prevajalnik javil napako. Parametri se morajo ujemati tako po številu kot po tipu. Če prototipa funkcije ne podamo, prevajalnik ne bo preverjal števila in tipa parametrov pri klicih take funkcije. Zato bo morda prevod programa brez opozoril, rezultati pri izvedbi programa pa bodo napačni.
Prototip napišemo tako, da preprosto kopiramo glavo funkcije na začetek
programa in ga zaključimo s podpičjem. Imena spremenljivk v prototipu
lahko sicer navedemo, vendar jih v resnici prevajalnik ignorira.
KOMPATIBLNI TIPI
Kompatibilni tipi so vsi preprosti tipi, ki jih lahko medsebojno smiselno pretvarjamo. Tako lahko imamo nek celoštevilčni parameter, funkcija pa morda formalno pričakuje parameter tipa float. Sistem bo sam avtomatsko opravil konverzijo. Enako velja za spremembo iz float v char ali iz char v int.
Če je kot formalni parameter funkcije naveden int, v klicu funkcije
pa navedemo kazalec na int, do konverzije ne more priti, saj sta
to dve popolnoma različni stvari. Podobno tudi ne bi prišlo do pretvorbe
neke strukture v long float, polje alo morda
celo v neko drugo obliko strukture, saj je smiselna pretvorba nemogoča.
Podobno velja tudi za vračani tip funkcije (v našem primeru void),
ki se mora ujemati z napovedanim oziroma pričakovanim tipom.
KAKO DELUJEJO PROTOTIPI?
Delovanje prototipov najlažje spoznamo s poskušanjem. Spremenimo aktualne parametre v vrstici 12 v (12.2, 13, 12345) in poglejmoč kaj poreče prevajalnik. Verjetno nič, ker so parametri kompatibilni. Opozorilo o napaki pa dobimo, če spremenimo parametre na (12.0, 13), ker jih nismo navedli dovolj. Napaka bi tudi bila, če bi pred enega od imen spremenljivk v vsrtici 13 dali znak &, s čemer bi na tem mestu navedli naslov spremenljivke. Tudi sprememba void v int v vrstici 4 bi povzročila izpis opozorila o napaki. Po popravku glave funkcije v vrstici 18 tako, da se bo ponovno ujemala s prototipom, to opozorilo izgine, zato pa ugotovimo, da nam funkcija ne vrača nič, kar pa prevajalniku spet ni všeč. Vidimo, da nam prototipi pomagajo pri iskanju napak v naših programih.
Primer programa ------> PROTYPE2.CPP
Poglejmo si sedaj naslednji primer v datoteki PROTYPE2.CPP. Program
je podoben prejšnjemu. Imena spremenljivk v prototipu v vrstici 4 so izpuščena
in tako spoznamo, da jih prevajalnik pravzaprav obravnava kot komentar.
POSREDOVANJE Z REFERENCO
Primer programa ------> PASSREF.CPP
Program PASSREF.CPP kaže posredovanje z referenco, kar pri ANSI-C ni mogoče. Referenčno spremenljivko smo že prej spoznali, ta primer pa kaže njeno uporabnost. Posredovanje z referenco omogoča prenos spremenljivke funkciji tako, da bodo njene spremembe opazne tudi v kličočem programu. Pri ANSI-C smo isto dosegli s posredovanjem kazalca na spremenljivko, vendar je ta metoda bolj jasna.
Prototip v vrstici 5 ima sedaj pred drugo spremenljivko znak &. Ta znak pove prevajalniku, da naj to spremenljivko obravnava kot referenco na resnično spremenljivko, ki jo posreduje kličoči program. V sami funkciji (vrstice 24 do 27) uporabljamo spremenljivko in2, ta poa se obnaša tako, kot bi uporabljali spremenljivko iz kličočega programa, ne pa njeno kopijo. Druga spremenljivka, in1 pa se obnaša tako, kot smo navajeni pri ANSI-C. Ime in2 je sinonim za spremenljivko z imenom index v glavnem programu, ime in1 pa velja za kopijo spremenljivke count glavnega programa.
V prototipu funkcije lahko imena spremenljivk tudi izpustimo in dobimo:
void fiddle(int, int&);Pascalski programerji spoznajo in1 kot normalen parameter v klicu funkcije, klican po vrednosti. Spremenljivko in2 pa obravnavamo kot spremenljivko ki ima spredaj besedico VAR, čemur pravimo klic po referenci.
Ob pridobivanju programerskih izkušenj spoznamo vso učinkovitost posredovanja
z referenco, še posebno, če poramo funkcijam posredovati kar podatkovne
strukture (saj zadošča posredovanje njihovega naslova).
PRIVZETI PARAMETRI
Primer programa ------> DEFAULT.CPP
Program DEFAULT.CPP kaže uporabo privzetih (default) parametrov pri C++. Prototip funkcije pove, da moramo pri vsakem klicu obvezno podati prvi parameter z imenom length, saj ni podana njegova privzeta (default) vrednost. Drugi parameter z imenom width pa ni obvezen pri vsakem klicu funkcije. Če ga ne navedemo, bo imela spremenljivka width znotraj funkcije vrednost 2. Podobno ni obvezen tretji parameter. Če ga ne navedemo, bo vrednost spremenljivke height v funkciji enaka 3.
V vsrtici 11 so navedeni vsi trije parametri in to ni nič nenavadnega. V vrstici 12 manjka navedba trethega parametra, zato se bo program obnašal tako, kot če bi klicali funkcijo get_volume(x,y,3). V vrstici 13 manjkata celo dva parametra. Tako se bo program obnašal, kot če bi uporabili klic get_volume(x,2,3).
Upoštevati moramo nekaj pravil. Če je za nek parameter v seznamu parametrov
uporabljena privzeta vrednost, bodo uporabljene privzete vrednosti tudi
za vse naslednje parametre, saj ne moremo imeti "luknje" v seznamu. Seveda
mora biti za privzete vrednosti uporabljen pravi tip. Privzete vrednosti
lahko navedemo bodisi v prototipu, bodisi v glavi funkcije (ne pa v obeh
hkrati). Stilistično je pametneje, če jih navajamo v prototipu funkcije.
SPREMENLJIVO ŠTEVILO ARGUMENTOV
Primer programa ------> VARARGS.CPP
Program VARARGS.CPP kaže primer s spremenljivim številom argumentov
v funkcijskem klicu. V nekaterih primerih si to želimo, spomnimo se na
primer funckije printf(). ANSI-C rešuje to z več makroji v
zaglavni datoteki "stdarg.h". To sicer lahko uporabimo tudi v
C++, radi pa bi poenostavili preverjanje tipa parametrov. To naredi za
nas zaporedje treh točk v vrstici 6. Prototip v našem primeru zahteva,
da je prvi argument tipa int is, morebitnih ostalih pa prevajalnik
ne bo preverjal .
Seveda lahko taka poenostavitev dovoli tvorbo nenavadne programske
kode, in se ji izogibajmo.
PREKRIVANJE IMEN FUNKCIJ
Primer programa ------> OVERLOAD.CPP
Program OVERLOAD.CPP kaže prekrivanje (preobremenjevanje, overloading) več imen funkcij. To izgleda nenavadno, vendar je ključnega pomena za objektno usmerjeno programiranje.
Imamo tri funkcije z enakim imenom. Katera funkcija bo torej poklicana ob izvedbi klica do_stuff()?" Klicana bo funkcija, pri kateri se z dejanskimi parametri ujemata tako število kot tudi tip formalnih parametrov. Če je v klicu do_stuff() navedeno kot parameter le eno celo število, bo klicana funkcija, ki začne v vrstici 25. Če je naveden en sam aktualni parameter tipa float, bo klicana funkcija z začetkom v vrstici 30. Če navedemo dva parametra tipa float, kličemo funkcijo v vrstici 36.
Na izbiro prekrivane funkcije vpliva le število in tip formalnih parametrov, ne pa tip vračanega rezultata funkcije.
Ključna beseda overload (vrstica 4) ni obvezujoča, napove pa našo namero definiranja več prekrivanih funkcij z imenom do_stufft. Pri novejših programih jo običajno opuščamo.
Katera od prekritih funkcij bo uporabljena, določi že prevajalnik, zato program v zasu izvajanja ni nič upočasnjen.