Přeskočit na obsah

Parametr funkce

Z Wikipedie, otevřené encyklopedie

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ř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ř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);
}

Související články

[editovat | editovat zdroj]