\documentclass[margin=0px]{article} \usepackage{listings} \usepackage[utf8]{inputenc} \usepackage{graphicx} \usepackage{float} \usepackage[a4paper, margin=1in]{geometry} \usepackage{amsthm} \usepackage{amssymb} \renewcommand{\figurename}{ábra} \makeatletter \renewcommand\paragraph{% \@startsection{paragraph}{4}{0mm}% {-\baselineskip}% {.5\baselineskip}% {\normalfont\normalsize\bfseries}} \makeatother \renewcommand{\figurename}{ábra} \newenvironment{tetel}[1]{\paragraph{#1}}{} % A dokument itt kezdődik \title{Záróvizsga tételsor \\ \large 10. Programnyelvi alapok} \date{} \author{Ancsin Ádám} \begin{document} \maketitle \begin{tetel}{Programnyelvi alapok} Kifejezések kiértékelésének szabályai. Vezérlési szerkezetek: utasítások, rekurzió. Típusok: tömb, rekord, osztály, öröklődés, statikus és dinamikus kötés, polimorfizmus. Generikusok. Hatókör/láthatóság. Automatikus, statikus és dinamikus élettartam, szemétgyűjtés. Konstruktor, destruktor. Objektumok másolása, összehasonlítása. Alprogramok, paraméterátadás, túlterhelés. \end{tetel} \section{Kifejezések kiértékelésének szabályai} \noindent Fogalmak: \begin{itemize} \item Operandusok: Változók, konstansok, függvény- és eljáráshívások. \item Operátorok: Műveleti jelek, amelyek összekapcsolják egy kifejezésben az operandusokat és valamilyen műveletet jelölnek. \item Kifejezés: operátorok és operandusok sorozata \item Precedencia: A műveletek kiértékelési sorrendjét határozza meg. \item Asszociativitás iránya: Az azonos precedenciájú operátorokat tartalmazó kifejezésekben a kiértékelés iránya. Megkülönböztetünk bal-asszociatív és jobb-asszociatív operátorokat. \end{itemize} \noindent Az operátorokat háromféleképpen írhatjuk az operandusokhoz képest: \begin{itemize} \item Infix : Egy operátort a két operandusa közé kell írni (tehát csak kétoperandusú műveletek operátorait lehet így írni). Amikor egy kifejezésben több operátor is szerepel, akkor a különböző operátorok végrehajtási sorrendjét az operátorok precedenciája dönti el. Amelyik operátor precedenciája magasabb (pl. a szorzásé magasabb, mint az összeadásé), az általa jelölt műveletet értékeljük ki először. Ugyanazon operátorok végrehajtási sorrendjét pedig az asszociativitás iránya dönti el (pl. a bal-asszociatív azt jelenti, hogy balról jobbra haladva kell végrehajtani). Ezeket a (programozási nyelvekbe beépített) szabályokat zárójelek segítségével lehet felülírni.\\ Példa: A * (B + C) / D \item Postfix (Lengyelforma) : Az operátorokat az operandusaik mögé írjuk. A kiértékelés sorrendje mindig balról jobbra történik – tehát egy n operandusú operátor a tőle balra levő első n operandusra érvényes.\\ Példa: A B C + * D /\\ Ugyanez zárójelezve (felesleges): ((A (B C +) *) D /) \item Prefix : Az operátorokat az operandusuk elé írjuk. A kiértékelés sorrendje balról jobbra történik.\\ Példa: / * A + B C D\\ Ugyanez zárójelezve (felesleges): (/ (* A (+ B C) ) D)\\ Habár a prefix operátorok esetén is balról jobbra történik a kiértékelés, viszont ha egy operátortól jobbra egy másik operátor következik, akkor értelemszerűen az ehhez az operátorhoz tartozó műveletet kell először végrehajtani, hogy a bal oldalit is végre tudjuk hajtani. A fenti példában is a szorzást az osztás előtt, az összeadást pedig a szorzás előtt kell elvégezni. \end{itemize} \paragraph{Logikai operátorokat tartalmazó kifejezések kiértékelése} \noindent Az ilyen kifejezéseknek kétféle kiértékelése létezik: \begin{itemize} \item Lusta kiértékelés : Ha az első argumentumból meghatározható a kifejezés értéke, akkor a másodikat már nem értékeli ki. \item Mohó kiértékelés : Mindenféleképpen megállapítja mindkét argumentum logikai értékét. \end{itemize} \noindent A két kiértékelési módszer bizonyos esetekben különböző eredményt adhat: \begin{itemize} \item A 2. argumentum nem mindig értelmes\\ Példa (C++): \begin{verbatim} if ((i>=0) && (T[i]>=10)) { //... } \end{verbatim} Tegyük fel, hogy a T egy \texttt{int} tömb, 0-tól indexelődik. Itt ha az $i>=0$ hamis, akkor T-t alul indexelnénk. Ez mohó kiértékelés esetén futási idejű hibát okozna. Lusta kiértékelés esetén (a C++ alapértelmezetten ezt használja) viszont tudhatjuk, hogy a feltétel már nem lehet igaz, emiatt $T[i]>=10$-et már nem kell kiértékelni. \item A 2. argumentumnak van valamilyen mellékhatása.\\ Példa (C++): \begin{verbatim} if ((i>0) || (++j>0)) { T[j] = 100; } \end{verbatim} Ebben az esetben ha $i>0$ igaz, akkor a feltétel biztosan igaz, viszont a $++j>0$ kifejezés mellékhatásos, növeli j értékét. Mivel a C++ lusta kiértékelést használ a $||$ operátor esetén ($|$ operátor esetén mohó a kiértékelés), ezért ebben az esetben nem növeli j értékét. (csak akkor, ha $i>0$ hamis). \end{itemize} \section{Utasítások, vezérlési szerkezetek} \subsection{Egyszerű utasítások} \begin{itemize} \item Értékadás : Az értékadás bal oldalán egy változó, a jobb oldalán bármilyen kifejezés állhat. Az értékadással a változóhoz rendeljük a jobb oldali kifejezést. Figyelni kell arra, hogy a bal oldali változó típusának megfelelő kifejezés álljon a jobb oldalon (vagy létezik implicit konverzió, pl. C++-ban az egész és logikai típus között). A legtöbb nyelvben az értékadás operátora az \texttt{=} (például C++, Java, C\#), vagy a \texttt{:=} (például Pascal, Ada). \item Üres utasítás : Nem mindenhol lehet ilyet írni. A lényege, hogy nem csinál semmit. Azokban a nyelvekben lehet létjogosultsága, ahol üres blokkot nem írhatunk, muszáj legalább 1 utasításnak szerepelnie benne. (pl. Ada) Erre szolgál az üres utasítás. (Ada-ban ez a \texttt{null} utasítás) \item Alprogramhívás : Alprogramokat nevük és paramétereik megadásával hívhatunk. Példák: \begin{itemize} \item \texttt{System.out.println("Hello”);} \item \texttt{int x = sum(3,4);} \end{itemize} \item Visszatérés utasítás : Az utasítás hatására az alprogram végrehajtása befejeződik. Ha az alprogram egy függvény, akkor meg kell adni a visszatérési értéket is. \noindent Példák (C++): \begin{itemize} \item Ebben a példában a \texttt{doSomething} egy eljárás, nincs visszatérési értéke. A paraméterül kapott x változót értékül adjuk a j-nek. Ha ez az érték nem 0, akkor visszatérünk, azaz megszakítjuk az alprogram végrehajtását (konkrét értéket viszont nem adunk vissza). Ha ez az érték 0, akkor a végrehajtás folytatódik tovább, meghívjuk a \texttt{doSomethingElse} függvényt a j paraméterrel. \begin{verbatim} void doSomething(int x) { int j; if(j=x) return; // j!=0, do nothing doSomethingElse(j); } \end{verbatim} \item Ebben a példában az \texttt{isOdd} egy függvény, \texttt{int} visszatérési értékkel. Megmondja a paraméterül kapott x egész számról, hogy páratlan-e. Ehhez bitenkénti ÉS művelettel "összeéseli" az x-et az 1-gyel (0...01). Ha az eredmény nem 0, akkor páratlan, visszatérünk igaz értékkel. Különben folytatjuk a működést, majd visszatérünk hamis értékkel. \begin{verbatim} int isOdd(int x) { if(x & 1) //bitwise AND with 0...01 is not 0...0 return true; return false; } \end{verbatim} \end{itemize} \item Utasításblokk: A blokkon belüli utasítások "összetartoznak”. Ez több esetben is jól alkalmazható nyelvi elem: \begin{itemize} \item Vezérlési szerkezetekben: Az adott vezérlési szerkezetekhez tartozó utasításokat különíthetjük el. \item Az olyan nyelvekben, amelyekben deklaráció csak a program elején található deklarációs blokkokban lehetséges (pl. Ada), van lehetőség arra, hogy a programkód későbbi részében nyissunk egy blokkot, ahol deklarációk is szerepelhetnek. \item Osztályok inicializáló blokkja pl. Java-ban (konstruktor előtt hajtódik végre): \begin{verbatim} public class MyClass{ private ResourceSet resourceSet; { resourceSet = new ResourceSetImpl(); UMLResourcesUtil.init(resourceSet); } /* ... */ } \end{verbatim} \item Osztályok statikus inicializáló blokkja pl. Java-ban: \begin{verbatim} public class MyClass{ private static ResourceSet resourceSet; static{ resourceSet = new ResourceSetImpl(); UMLResourcesUtil.init(resourceSet); } /* ... */ } \end{verbatim} \end{itemize} \end{itemize} \subsection{Vezérlési szerkezetek} \begin{itemize} \item Elágazás : Az elágazás egy olyan vezérlési szerkezet, amellyel meghatározhatjuk, hogy bizonyos (blokkban megadott) utasítások csak a megadott feltétellel jöhessenek létre. Általában több feltételt is megadhatunk egymás után (if L1 then … else if L2 then … else if L3 then …). Megadhatjuk azt is, hogy mi történjen, ha egyik feltétel sem teljesül (if L then … else …). Elágazásokat lehet egymásba ágyazni (if … then if ...). "Csellengő else” ("Dangling else”) probléma: Azokban a nyelvekben lép fel, ahol egy feltétel egy utasításblokkját nem zárja le külön kódszó (pl. endif). Ekkor abban az esetben, ha elágazásokat egymásba ágyazunk, a következő probléma léphet fel:\\ Példa: \texttt{if (A>B) then if (C>D) then E:=100; else F:=100;} A fenti esetben nem lehet megállapítani, hogy a programozó az else kulcsszót melyik elágazásra értette. \item Ciklus : Egy utasításblokk (ciklusmag) valahányszori végrehajtását jelenti. \begin{itemize} \item Feltétel nélküli ciklus : Végtelen ciklust kódol, kilépni belőle a strukturálatlan utasításokkal lehet (ld. lentebb), vagy return-nel, esetleg hiba fellépése esetén. Példa (ADA): \begin{verbatim} loop null; end loop; \end{verbatim} \item Elöltesztelő ciklus : A ciklus a ciklusmag minden végrehajtása előtt megvizsgálja, hogy az adott feltétel teljesül-e. Ha teljesül, akkor végrehajtja a magot, majd újra ellenőriz. Különben a ciklus után folytatódik a futás. Példák: \begin{itemize} \item C++: \begin{verbatim} int x=0,y=0; while(x<5 && y<5) { x+=y+1; y=x-1; } cout<0) return n * fact (n-1); else return 1; } \end{verbatim} \item Haskell: \begin{verbatim} fact :: (Integral a) => a -> a fact n | n>0 = n * fact (n - 1) | otherwise = 0 \end{verbatim} \end{itemize} \section{Típusok} \subsection{Tömb} A tömb (angolul array) olyan adatszerkezet, amelyet nevesített elemek csoportja alkot, melyekre sorszámukkal (indexükkel) lehet hivatkozni. Vektornak is nevezik, ha egydimenziós, mátrixnak esetenként, ha többdimenziós. A legtöbb programozási nyelvben minden egyes elemnek azonos adattípusa van és a tömb folytonosan helyezkedik el a számítógép memóriájában. A készítés módja alapján lehet: \begin{itemize} \item statikus :a méret fix, deklarációban szabályozott \item dinamikus tömb: a mérete változik, folyamatosan bővíthető \end{itemize} \subsection{Rekord} A rekord egy összetett értékek leírásához használható konstrukció. Névvel és típussal ellátott összetevői vannak, ezeket mezőknek nevezzük. Értékhalmaz a mezők értéktípusai által meghatározott alaphalmazok direktszorzata. \begin{figure}[H] \centering \includegraphics[width=0.7\linewidth]{img/rekord} \caption{A rekord-típuskonstrukciók általános szintaxisa.} \label{fig:rekord} \end{figure} \noindent Műveletek: \begin{itemize} \item Szelekciós függvény (.mezőszelektor szintaxisú); \item konstrukciós függvény (Rekordtípus(mezőértékek) szintaxisú); \item elképzelhetők transzformációs függvények, amelyek a teljes rekordstruktúrát érintik. \end{itemize} \noindent Példa rekordra és használatára C-ben: \begin{verbatim} //definition of Point struct Point { int xCoord; int yCoord; }; const struct Point ORIGIN = {0,0}; \end{verbatim} \subsection{Osztály} Az osztály egy felhasználói típus, amelynek alapján példányok (objektumok) hozhatók létre. Az osztály alapvetően attribútum és metódus (művelet) definíciókat tartalmaz. Az osztály írja le az objektum típusát: megadja a tulajdonságait és azok lehetséges értékeit (azaz a típusértékeket), valamint az objektumon végrehajtható műveleteket (típusműveletek).\\ \noindent Példa C++-ban: \begin{verbatim} //definition of Point class Point { private: int xCoord; int yCoord; public: //constructor Point(int xCoord, int yCoord) : xCoord(xCoord),yCoord(yCoord) {} void Translate(int dx, int dy) { xCoord+=dx; yCoord+=dy; } void Translate(Point delta) { xCoord+=delta.xCoord; yCoord+=delta.yCoord; } int getX() { return xCoord; } int getY() { return yCoord; } }; int main(int argc, char* argv[]) { Point point(0,0); point.Translate(5,-2); cout<; function Square (X : Element_T) return Element_T; \end{verbatim} Itt a \texttt{with function} kezdetű sor végén az \texttt{is <>} azt jelenti, hogy ha az adott típusra már létezik * művelet (pl. egész számokra), akkor nem kell külön megadni példányosításkor, a program automatikusan azt használja. A törzs: \begin{verbatim} function Square (X: Element_T) return Element_T is begin return X * X; -- The formal operator "*". end Square; \end{verbatim} \item A példányosításnak biztosítania kell mindent, amit a sablon specifikációja megkövetel tőle. A következő példában a négyzetre emelő függvényt mátrixokra alkalmazzuk, feltéve, hogy definiáltuk a mátrixszorzást. \begin{verbatim} with Square; with Matrices; procedure Matrix_Example is function Square_Matrix is new Square (Element_T => Matrices.Matrix_T, "*" => Matrices.Product); A : Matrices.Matrix_T := Matrices.Identity; begin A := Square_Matrix (A); end Matrix_Example; \end{verbatim} \end{itemize} Például a C++-ban a sablonszerződés nem így működik. Ott a sablon specifikációja az egész definíció (emiatt sablonosztályokat csak teljes egészében header fájlokban definiálhatunk). Példányosításkor ezt is ismerni kell, hogy tudjuk, hogyan példányosíthatunk. Az információelrejtés elve tehát sérül. Más nyelvekben (pl. Java, funkcionális nyelvek) nem kell a sablonokat példányosítani – mindig ugyanaz a megírt kód hajtódik végre, csak épp az aktuális paraméterekkel. Pl. Java-ban a típusparaméter fordításkor "elveszik", csak futási időben derül ki. \section{Hatókör/láthatóság} \begin{enumerate} \item Hatókör: Deklarációkor a programozó összekapcsol egy entitást (például egy változót vagy függvényt) egy névvel. A hatókör alatt a forrásszöveg azt a részét értjük, amíg ez az összekapcsolás érvényben van. Ez általában annak a blokknak a végéig tart, amely tartalmazza az adott deklarációt. \item A láthatóság a hatókör részhalmaza, a programszöveg azon része, ahol a deklarált névhez a megadott entitás tartozik. Mivel az egymásba ágyazott blokkokban egy korábban már bevezetett nevet más entitáshoz kapcsolhatunk, ezért ilyenkor a külső blokkban deklarált entitás a nevével már nem elérhető. Ezt nevezzük a láthatóság elfedésének. Egyes nyelvekben (például C++) bizonyos esetekben (például osztályszintű adattagok) a külső blokkban deklarált entitáshoz minősített névvel hozzá lehet férni ekkor is. \end{enumerate} \section{Automatikus, statikus és dinamikus élettartam, szemétgyűjtés} Élettartam: A változók élettartama alatt a program végrehajtási idejének azt a szakaszát értjük, amíg a változó számára lefoglalt tárhely a változóé. \subsection{Automatikus élettartam} A blokkokban deklarált lokális változók automatikus élettartamúak, ami azt jelenti, hogy a deklarációtól a tartalmazó blokk végéig tart, azaz egybeesik a hatókörrel. A helyfoglalás számukra a végrehajtási verem aktuális aktivációs rekordjában történik meg. \subsection{Statikus élettartam} A globális változók, illetve egyes nyelvekben a statikusként deklarált változók (például C/C++ esetén a \texttt{static} kulcsszóval) statikus élettartamúak. Az ilyen változók élettartama a program teljes végrehajtási idejére kiterjed, számukra a helyfoglalás már a fordítási időben megtörténhet. \subsection{Dinamikus élettartam} A dinamikus élettartamú változók esetén a programozó foglal helyet számukra a dinamikus tárterületen (heap), és a programozó feladata gondoskodni arról is, hogy ezt a tárterületet később felszabadítsa. Amennyiben utóbbiról megfeledkezik, azt nevezzük memóriaszivárgásnak (memory leak). Mint látjuk, a dinamikus élettartam esetén a hatókör semmilyen módon nem kapcsolódik össze az élettartammal, az élettartam szűkebb vagy tágabb is lehet a hatókörnél. \subsection{Szemétgyűjtő} A szemétgyűjtő másik neve a hulladékgyűjtő, az angol Garbage Collector név után pedig gyakran csak GC-nek rövidítik. Feladata a dinamikus memóriakezeléshez kapcsolódó tárhelyfelszabadítás automatizálása, és a felelősség levétele a programozó válláról, így csökkentve a hibalehetőséget. A szemétgyűjtő figyeli, hogy mely változók kerültek ki a hatókörükből, és azokat felszabadíthatóvá nyilvánítja. A módszer hátránya a számításigényessége, illetve a nemdeterminisztikussága. A szemétgyűjtő ugyanis nem szabadítja fel egyből a hatókörükből kikerült változókat, és a felszabadítás sorrendje sem ugyanaz, amilyen sorrendben a változók felszabadíthatóvá váltak. Azt, hogy a hulladékgyűjtő mikor és mely változót szabadítja fel, egy programozási nyelvenként egyedi, összetett algoritmus határozza meg, amelyben rendszerint szerepet játszik a rendelkezésre álló memória telítettsége, illetve a felszabadításhoz szükséges becsült idő. (Például ha egy objektum rendelkezik destruktorral, akkor általában a GC később szabadítja csak fel.) Összességében a szemétgyűjtő csak annyit garantál, hogy előbb-utóbb (legkésőbb a program futásának végeztével) minden dinamikusan allokált változót felszabadít. Szemétgyűjtést használó nyelvek pl. Java, C\#, Ada. C/C++-ban nincs szemétgyűjtés, a programozónak kell gondoskodni a dinamikusan allokált memóriaterületek felszabadításáról. \section{Konstruktor, destruktor} \subsection{Konstruktor} A konstruktor az objektumok inicializáló eljárása, akkor fut le, ha egy osztályból új objektumot példányosítunk. Alapértelmezett konstruktor alatt a paraméter nélküli konstruktort értjük, a legtöbb programozási nyelv esetén ezt a fordítóprogram automatikusan generálja üres törzzsel, amennyiben nem lett megadva egy konstruktor sem egy osztályban. Többek között a konstruktorban szokás gondoskodni arról, hogy az objektum dinamikus élettartamú változói számára tárhelyet foglaljunk. \subsection{Destruktor} A destruktor a konstruktor ellentétes párja, ez az eljárás az objektumok felszabadításakor fut le. Meghívása automatikusan megtörténik, attól függetlenül, hogy az objektum felszabadítása automatikusan történik a hatókör végeztével (lokális objektumok esetén), manuálisan a programozó által (dinamikus élettartamú objektumok esetén) vagy a szemétgyűjtő által (szintén dinamikus élettartamú objektumok esetén). A desktruktorban szokás többek között az objektum dinamikus helyfoglalású adattagjait és a lefoglalt erőforrásokat felszabadítani. \section{Objektumok másolása, összehasonlítása} Az objektumok másolása egy speciális konstruktorral, az úgynevezett másoló konstruktorral (copy constructor) történik. Ez paraméterül az adott osztály egy példányát kapja meg, és azt a programozó által megadott működési logika szerint lemásolja az éppen inicializált objektumba. Több programozási nyelv (például C++) fordítóprogramja automatikusan elkészít egy másoló konstruktort, ha a programozó nem definiál sajátot. Ez az alapértelmezett másoló konstruktor lemásolja a forrásobjektum összes adattagjának értékét, ezt nevezzük sekély másolatnak (shallow copy). Ha az objektum dinamikus foglalású adattagokat is tartalmaz, akkor azoknak nem az értéke, hanem csak a hivatkozása lesz lemásolva, ami általában nem a kívánt működés. Ez esetben saját másoló konstruktor írása szükséges, ami mély másolatot (deep copy) készít. \section{Alprogramok, paraméterátadás, túlterhelés} \subsection{Alprogramok} Alprogramoknak a függvényeket, eljárásokat és műveleteket nevezzük. Segítségükkel a program feladatonként tagolható, a főprogramból az önálló feladatok kiszervezhetőek. \subsection{Paraméterátadás} Az alprogramoknak szüksége lehet bemenő adatokra és vissza is adhat értékeket. Az alprogramokat általános írjuk meg, saját változónevekkel, ezek a formális paraméterek. Az alprogram meghívásakor az átadott aktuális paraméterek alapján a formális paraméterek értéket kapnak. Az, hogy a formális paraméterek értéke mi lesz, a paraméterátadás módjától függ. \subsubsection{Szövegszerű paraméterátadás} A makrókban használatosak mind a mai napig. A makró törzsében a formális paraméter helyére beíródik az aktuális paraméter szövege. \subsubsection{Név szerinti paraméterátadás} Az aktuális paraméter kifejezést újra és újra kiértékeljük, ahányszor hivatkozás történik a formálisra. A paramétert a törzs kontextusában értékeljük ki, így a formális paraméter különböző előfordulásai mást és mást jelenthetnek az alprogramon belül. Alkalmazása archaikus (például: Algol 60, Simula 67). \subsubsection{Érték szerinti paraméterátadás} Az egyik legelterjedtebb paraméterátadási mód (például: C, C++, Pascal, Ada, Java), bemeneti szemantikájú. A formális paraméter az alprogram lokális változója, híváskor a vermen készül egy másolat az aktuális paraméterről, ez lesz a formális. Az alprogram végén a formális paraméter megszűnik \subsubsection{Cím szerinti paraméterátadás} A másik legelterjedtebb paraméterátadási mód (például: Pascal, C++, C\#), be- és kimeneti szemantikájú. A híváskor az aktuális paraméter címe adódik át, azaz a formális és az aktuális paraméter ugyanazt az objektumot jelentik, egy alias jön létre.\\ Megjegyzés: A Java-ban nincs cím szerinti paraméterátadás, csak érték szerinti. A Java ugyanis a primitív típusoknak az értékét tárolja, objektumok esetén pedig egy referenciát az adott objektumra (mint C++-ban a referencia típus). Objektum átadásakor ez a referencia másolódik le, azaz a referencia adódik át érték szerint.\\ \noindent Például: \begin{verbatim} public static void BadSwap(Object x, Object y) { Object tmp = x; x = y; y = tmp; } \end{verbatim} A fenti függvény nem cseréli ki az x-et és y-t, csak lokálisan (a függvénytörzsön belül), viszont a hívás helyén x és y is helyben maradnak. \subsubsection{Eredmény szerinti paraméterátadás} Kimeneti szemantikájú paraméterátadási mód. A formális paraméter az alprogram lokális változója, az alprogram végén a formális paraméter értéke bemásolódik az aktuálisba. Azonban az alprogram meghívásakor az aktuális értéke nem másolódik be a formálisba. (Használja például az Ada.) \subsubsection{Érték/eredmény szerinti paraméterátadás} Az érték és eredmény szerinti paraméterátadás összekombinálása, így egy be- és kimeneti szemantikájú paraméterátadási módot kapunk. (Használja például az Algol-W vagy az Ada.) \subsubsection{Megosztás szerinti paraméterátadás} Objektumorientált programozási nyelvek (például: CLU, Eiffel) paraméterátadási módja. Lényege, hogy ha a formális paraméter megváltoztatható és az aktuális paraméter egy megváltoztatható változó, akkor cím szerinti paraméterátadás történik, egyébként pedig érték szerinti. A paraméterátadás módját külön megadni nem lehet. Megváltoztatható (mutable) objektum alatt azt értjük, hogy tulajdonságai, ezáltal állapota megváltoztatható. \subsubsection{Igény szerinti paraméterátadás} Ezt a paraméterátadási módot a lusta kiértékelésű funkcionális nyelvek (például: Clean, Haskell, Miranda) alkalmazzák. Az aktuális paramétert nem híváskor értékeli ki, hanem akkor, amikor először szüksége van rá a számításokhoz. \subsection{Túlterhelés} A túlterhelés (overloading) segítségével azonos nevű alprogramokat hozhatunk létre eltérő szignatúrával. A szignatúra a legtöbb programozási nyelvben az alprogram nevét és a formális paraméterek számát és típusát jelenti, de egyes nyelvekben (például Ada) a visszatérési érték típusa is beletartozik. A túlterhelés elsődleges felhasználási területe, hogy ugyanazt a tevékenységet különböző paraméterezéssel is elvégezhessük. A fordító az alprogramhívásból el tudja dönteni, hogy a túlterhelt változatok közül melyiket kell meghívni. Ha egyik sem illeszkedik vagy több is illeszkedik, akkor fordítási hiba lép fel. \end{document}