Parametr funkce
Parametr funkce je označení pro vstupní data funkce v programování.
Formální a skutečný parametr
[editovat | editovat zdroj]Tento pojem ve skutečnosti zahrnuje dvě odlišné věci:
- Formální parametr je parametr použitý při psaní funkce, její vnitřní proměnná. Ta je vždy před zpracováním nahrazována hodnotou skutečného parametru.
- Skutečný parametr je proměnná nebo výraz dosazený při volání funkce. Při volání funkce je jeho hodnota přiřazena formálnímu parametru.
Způsoby předávání parametru
[editovat | editovat zdroj]Navázání skutečného parametru na formální lze dosáhnout několika odlišnými způsoby. Ve většině dnešních programovacích jazyků se používají hlavně předávání parametrů hodnotou a odkazem:
- Při předávání hodnotou (call-by-value) se těsně před zpracováním těla funkce skutečný parametr vyčíslí a výsledek se zkopíruje do lokální proměnné uvnitř volané funkce. Jakékoli změny parametru uvnitř volané funkce nemají vliv na volající funkci, neboť se pracuje s lokální kopií, předávání hodnotou tedy lze používat pouze pro vstupní parametry. Tento způsob je typický např. při vytváření aritmetických funkcí.
- Při předávání odkazem (call-by-reference) se formální parametr uvnitř volané funkce bere jen jako jiné označení (alias) pro proměnnou předanou jako skutečný parametr, tzn. ve volané funkci se pracuje přímo s předávanou proměnnou, nevytváří se tedy kopie (což zvláště u strukturovaných proměnných znamená zpravidla úsporu času i paměti). Volaná funkce změnou parametru ovlivňuje i volající funkci (takže předávání odkazem lze používat pro výstupní či vstupně-výstupní parametry), nevýhodou však je, že parametrem může být jen proměnná a nikoli výsledek obecného výrazu. Předávání odkazem se obvykle implementuje pomocí ukazatele na předávanou proměnnou.
Někdy se používají také o něco netradičnější způsoby předávání jako např. předání hodnotou s kopií při návratu (call-by-copy-restore) nebo předání jménem (call-by-name).
Příklady
[editovat | editovat zdroj]Předávání jménem
[editovat | editovat zdroj]Předávání jménem se příhodně používá ve funkcionálních jazycích, v makrojazycích a skriptovacích jazycích využívajících textové nahrazování (Tcl). Z procedurálních kompilovaných jazyků bylo použito např. v Algolu 60, ale v těchto jazycích jde o anachronismus způsobený špatnou představou tvůrců jazyka o fungování překladačů. Výsledný efekt se podobá předávání referencí, ovšem hodnota parametru se v těle funkce vyhodnocuje při každém použití.
Příklad:
procedure P(X); integer X; begin write(X); I:=I+1; write(X); end
Při zavolání funkce:
P(A[i]);
se pak vypíší prvky v poli A na místě I a I+1.
Příklad v jazyce C
[editovat | editovat zdroj]Předávání hodnotou
void Zamen(int a, int b) //zameni hodnoty v promennych
{
int pom;
pom = a;
a = b;
b = pom;
}
Tuto metodu budeme volat v programu následovně:
int main(void)
{
int promennaA = 10, promennaB = 20;
Zamen(promennaA, promennaB);
return 0;
}
Po tomto zavolání metody Zamen budou hodnoty v proměnných promennaA 10 a v proměnné promennaB bude hodnota 20. Tedy k žádné změně nedojde. Je to tím, že pokud předáváme parametry funkci hodnotou, tak pracujeme vlastně s kopiemi proměnných a tím je průběh funkce izolovaný.
Pokud chceme, aby volání funkce ovlivnilo parametry, které předáváme, musíme předávat parametry funkci ukazatelem (referencí) na danou proměnnou.
Předávání ukazatelem
void Zamen(int* a, int* b) //zameni hodnoty v promennych
{
int pom = *a;
*a = *b;
*b = pom;
}
Tuto metodu budeme volat v programu následovně:
int main(void)
{
int promennaA = 10, promennaB = 20;
Zamen(&promennaA, &promennaB);
return 0;
}
Po zavolání funkce tímto způsobem se již odkazuje na místo v paměti, kde jsou uložené proměnné promennaA a promennaB a tím dosáhneme toho, že po zpracování funkce bude v proměnné promennaA hodnota 20 a v proměnné promennaB bude 10.
Příklad v jazyce C#
[editovat | editovat zdroj]Předávání parametrů v jazyce C# je velice podobné jazyku C, jen zde dochází k malé změně definice a volání takové funkce.
Předávání hodnotou
void Zamen(int a, int b)
{
int pom = a;
a = b;
b = pom;
}
Tuto metodu budeme volat v programu následovně:
static void Main(string[] args)
{
int promennaA = 10;
int promennaB = 20;
Zamen(promennaA, promennaB);
}
Jak můžeme vidět, tak předávání parametrů funkci hodnotou v jazyce C# je totožné s jazykem C a dočkáme se i stejného výsledku, tj. promennaA a promennaB budou po zavolání funkce beze změny.
Předávání odkazem
void Zamen(ref int a, ref int b) // zameni hodnoty v promennych
{
int pom = a;
a = b;
b = pom;
}
Tuto metodu budeme volat v programu následovně:
static void Main(string[] args)
{
int promennaA = 10;
int promennaB = 20;
Zamen(ref promennaA, ref promennaB);
}
Po předání parametrů funkci tímto způsobem dosahujeme stejného výsledku jako v jazyce C a ve výsledku máme tedy po zavolání funkce v našich proměnných promennaA a promennaB hodnotu 20 resp. 10.
Jazyk C# umí navíc další možnosti jak předávat parametry funkci. Je zde možnost proměnného počtu parametrů funkce a také možnost použití modifikátoru out, který je blízký modifikátoru ref. Na následujících příkladech si ukážeme funkčnost těchto možností.
Proměnný počet parametrů
int Suma(params int[] cisla) // secte vsechna cisla zadana jako parametry
{
int suma = 0;
for (int i = 0; i < cisla.Length; i++)
{
suma += cisla[i];
}
return suma;
}
Tuto metodu budeme volat v programu následovně:
static void Main(string[] args)
{
int suma = Suma(1, 2, 3, 4, 5); // libovolny pocet parametru typu int
}
Předání odkazem (modifikátor out)
Tato možnost předání parametru funkci je podobná jako u předávání odkazem (ref). Tento zápis používáme, pokud potřebujeme z funkce například více výstupů. Například potřebujeme zjistit, jestli se výpočet funkce provedl v pořádku, a tak funkce vrací hodnotu bool a výsledek je tedy potřeba získat přes modifikátor out. Bylo by možné použít i možnost ref, ale při použití modifikátoru out je nucen programátor parametr funkce s tímto modifikátorem ve funkci naplnit. Alternativním řešením by bylo použití typu int?, který podporuje navíc i hodnotu null, která by značila neúspěch.
// secte hodnoty a, b a ulozi do prommene, ktera je jako parametr soucet, a vraci typ bool, zdali se soucet povedl
bool Soucet(int a, int b, out int soucet)
{
try
{
soucet = a + b; // pokud je nejaky parametr out, je nutne ho v tele funkce pouzit (na rozdil od ref)
return true;
}
catch (Exception)
{
soucet = 0;
return false; // soucet se nepovedl
}
}
Tuto metodu budeme volat v programu následovně:
static void Main(string[] args)
{
int a = 10;
int b = 20;
int soucet;
bool vypocetOK = Soucet(a, b, out soucet);
}