5. díl - Přetěžování a statika u funkcí

C a C++ C++ Pokročilé konstrukce v C++ Přetěžování a statika u funkcí

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulém díle, Reference v C++, jsme řešili reference. Dnes se podíváme opět na funkce, ale řekneme si doplňující informace, které nebyly probrány v základech,

Přetěžování funkcí

Přetížení funkce znamená mít více funkcí se stejným jménem ale jinými parametry. Můžeme mít například funkci reprezentující nějakou matematickou operaci. Pravděpodobně bychom chtěli povolit všechny číselné typy jako parametr. To znamená, že budeme volat stejnou funkci pro typ int i pro typ double. To provedeme právě přetížením:

int secti(int a, int b)
{
    return a+b;
}

double secti(double a, double b)
{
    return a+b;
}

int main()
{
    int soucet1 = secti(1,1);
    double soucet2 = secti(1.0, 2.3);
    cout << soucet1 << " " << soucet2 << endl;
}

Vidíme, že máme dvě funce se stejným názvem ale jinými parametry. Říkáme, že funkce je přetížená. Kompilátor se na základě parametrů rozhodne, které přetížení použít v jakém případě. Tento výběr je relativně komplikovaný a rozlišují se různé převody mezi typy. Zájemci se mohou podívat do oficiální dokumentace, vzhledem ke složitosti a rozsahu problému nebudu toto téma dopodrobna rozebírat.

Důležité je, že kompilátor vybere funkci s nejlepší shodou. Například v prvním případě kompilátor vybral první přetížení, protože oba parametry jsou typu int. Ve druhém případě jsou oba parametry typu double, a tak kompilátor vybral druhé přetížení. Pokud by byly parametry namíchány (například první parametr by byl typu int a druhý typu double), potom přichází na řadu hledání nejlepší shody. V tomto případě by se použilo druhé přetížení, protože int lze implicitně převést na double, zatímco double na int nikoliv.

Z kódu výše je patrné, že implementace nemusí být shodná. Ve skutečnosti může být naprosto odlištná. Můžeme mít například funkci vypis, která vypíše data, které dostane jako parametr. Pokud budeme chtít vypsat vlastní strukturu, musíme přidat přetížení, které strukturu transformuje do textové podoby. Tento algoritmus bude jistě jiný pro každou strukturu, kterou v programu používáme.

struct Uzivatel
{
    string jmeno;
    int vek;
};

struct Letadlo
{
    double vykon_motoru;
    char oznaceni[255];
};

void vypis(Uzivatel u)
{
    cout << "Uzivatel " << u.jmeno << " kteremu je " << u.vek << endl;
}

void vypis(Letadlo l)
{
    cout << "Letadlo " << l.oznaceni << " s vykonem " << l.vykon_motoru << endl;
}

Později se dostaneme k lepšímu způsobu, jak struktury vypisovat, ale prozatím můžeme využít přetěžování metod a nechat kompilátor, ať si sám rozhodne, kterou implementaci použije.

Statické proměnné

Statika je v programování něco, co je globální. Prozatím si ukážeme statiku pouze u funkcí, později (v kurzu o OOP) si ukážeme statiku u tříd. Představme si funkci, která nám vytváří nějakou strukturu. Co když cheme do struktury uložit pořadí, ve kterém byla vytvořena. S dosavadními znalostmi bychom napsali něco následujícího:

int pocet = 0;

struct Uzivatel
{
    string jmeno;
    int vek;
    int poradi;
};

Uzivatel vytvorUzivatele()
{
    Uzivatel u;
    cout << "Zadejte jmeno: ";
    cin >> u.jmeno;
    cout << "Zadejte vek: ";
    cin >> u.vek;
    u.poradi = pocet;
    pocet++;
    return u;
}

Tento přístup bude fungovat, ale není moc šťastný. V tuto chvíli máme globální proměnnou, ke které je přístup ze všech částí programu. Můžeme omylem nadefinovat novou proměnnou se stejným názvem nebo data omylem přepsat. Obecně by se globální proměnné měli používat co nejméně, protože zpravidla hovoří o špatném návrhu programu. Pokud se chceme globální proměnné vyhnout, můžeme využít statiky.

Statická proměnná je svým způsobem globální proměnná, ale lze k ní přistupovat pouze uvnitř funkce. Na rozdíl od klasické proměnné zůstává ve statické proměnné hodnota mezi voláními funkce. To znamená, že pokud funkci zavoláte poprvé a do statické proměnné uložíte hodnotu 5, potom při druhém volání metody bude v proměnné stále hodnota 5. Statické proměnné zabezpečují, že se k hodnotě nikdo jiný než konkrétní funkce nedostane, ale stále se jedná o špatnou praxi, protože se jedná pouze o "zabezpečenou" globální proměnnou. Statickou proměnnou definujeme klíčovým slovem static.

struct Uzivatel
{
    string jmeno;
    int vek;
    int poradi;
};

Uzivatel vytvorUzivatele(string jmeno, int vek)
{
    static int pocet = 0; //tento řádek se vyhodnotí pouze jednou
    Uzivatel u;
    u.jmeno = jmeno;
    u.vek = vek;
    u.poradi = pocet;
    pocet++;
    return u;
}

int main()
{
     Uzivatel prvni = vytvorUzivatele("Pavel", 18);
     Uzivatel druhy = vytvorUzivatele("Karel", 19);
     cout << "prvni: " << prvni.poradi << endl;
     cout << "druhy: " << druhy.poradi << endl;
     return 0;
}

První uživatel bude mít uloženou hodnotu 0, zatímco druhý 1. Pokud bychom vytvořili ještě třetího uživatele, poté by měl hodnotu 2 atd.

Konzolová aplikace
prvni: 0
druhy: 1

Jak bylo řečeno, statické proměnné nevylepšují návrh programu, ale alespoň omezují viditelnost globální proměnné pro ostatní části programu.

Tím je dnešní díl u konce. Jedná se o témata, která jsou pouze v C++ a v C přetěžování funkcí ani statické proměnné nejsou. Proto si dejte pozor, kdybyste někdy byly nuceni programovat v čistém C. Příště, Pokročilé operace s pamětí v jazyce C++, si ukážeme dynamickou alokaci polí.


 

 

Článek pro vás napsal patrik.valkovic
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Miniatura
Předchozí článek
Reference v C++
Miniatura
Všechny články v sekci
Pokročilé konstrukce C++
Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!