Strukturované datové typy
C++ 11

image_printTisk

Při psaní jakéhokoliv programu si nevystačíme často jen v čísly a texty. Potřebujeme třeba si například definovat náš vlastní datový Zákazník, který bude reprezentovat nějaký pojem v problémové doméně naší aplikace. K tomu nám mohou posloužit dva způsoby definice vlastních datových typů “záznam”, které se skládají s dalších položek. Jsou to struktury a třídy.

Strukturovaný datový typ je datový typ, který se skládá s dalších datových typů. Ty mohou být jak atomické, například čísla nebo texty, nebo složené s dalších vlastních, uživatelsky definovaných, datových typů. Je to v podstatě datový typ složený z nějakých položek.

Tento datový typ můžeme definovat buď pomocí struktury nebo pomocí třídy. Pojem třída si v tomto článku vysvětlíme zatím zjednodušeně tak, že na rozdíl od struktury, třída může obsahovat kromě definovaných položek, tak i příkazy, které se nazývají metody a pomáhají nám pracovat s tímto novým datovým typem.

Blíže o třídách a všem, co s nimi souvisí, se dozvíte v druhé části těchto stránek, které pojednávají o objektivním programování v C++.

Definice struktury

Struktura je v podstatě záznam nebo soubor hodnot, které tento uživatelsky definovaný typ obsahuje. Ukažme si napřed na příkladu definici takové struktury:

#include <string>
using namespace std;

struct Zakaznik {
    string jmeno;
    string prijmeni;
    int vek;
};

Na příkladu je vidět, že definice nového datového typu Zakaznik se provede tak, že uvedeme klíčové slovo struct, za ním následuje název nového datového typu a pak ve složených závorkách uvádíme definici položek, jinak řečeno atributů struktury. Definice struktury musí být ukončena středníkem. Jednotlivé atributy jsou pak definovány tak, že uvedeme jejich datový typ, potom název a definici opět musíme ukončit znakem středník.

Nyní přejděme k příkladu, kde si ukážeme, jak takový nový datový typ použít a jak přistupovat k jednotlivým atributům našeho nového datového typu:

#include <string>
#include <iostream>
using namespace std;

struct Zakaznik {
    string jmeno;
    string prijmeni;
    int vek;
};

int main() {
    Zakaznik zakaznik;
    zakaznik.jmeno = "Michal";
    zakaznik.prijmeni = "Chaloupka";
    zakaznik.vek = 22;
    
    cout << "Jméno: " << zakaznik.jmeno << " " << zakaznik.prijmeni << endl;
    cout << "Věk: " << zakaznik.vek << endl;
    
    return 0;
}

Na příkladu je vidět zopakovaná definice struktury reprezentující datový typ Zákazníka s položkami jména, příjmení a věku. Po té ve funkci main deklarujeme proměnnou našeho nového datového typu Zákazník úplně stejně jako jiný vestavěný datový typ. Uvede se tedy název struktury a poté název proměnné. Opět ukončíme deklaraci středníkem.

Potom začneme vyplňovat hodnoty jednotlivých atributů zákazníka. To se provádí tak, že uvedeme název proměnné, tedy v našem případě zakaznik, potom zapíšeme tečku a následně uvedeme hodnotu atributu, ke kterému chceme přistupovat. Takto můžeme jak nastavit hodnoty atributu, tak je i získat, jak ukazuje další část příkladu, kde jsou hodnoty položek zákazníka vypisovány na standardní výstup.

Je důležité si uvědomit, že struktura by měla primárně sloužit jako jakási “přepravka” dat a pokud potřebujeme datový typ i s nějakým propracovanějším chováním pomocí metod, je z formálního hlediska vhodnější použít definici pomocí třídy, jak si ukážeme dále v tomto článku.

Definice třídy

Nyní si ukážeme na dalším příkladu definici stejného datového typu zákazníka, ale tentokrát v podobě třídy a navíc doplněné o funkce, které patří svojí definicí ke třídě a jsou nazývané metodami.

#include <string>

class Zakaznik {
    string jmeno;
    string prijmeni;
    int vek;
public:
    void nastavJmeno(const string& jm, const string& pr) { 
        jmeno = jm;
        prijmeni = pr;
    }

    const string& vratJmeno() { return jmeno; }
    const string& vratPrijmeni() { return prijmeni; }

    void nastavVek(int v) {
        vek = v;
    }
    int vratVek() { return vek; }

    void zvysVek() {
        vek = vek + 1;
    }
};

Na příkladu je vidět první rozdíl. Třída je uvozena klíčovým slovem class, místo struct, a po té následuje její název. Dále jsou uvedeny deklarace atributů jako u struktury, ale s jedním rozdílem. Nejsou veřejně přístupné, čili nemůžeme k nim přistupovat pomocí znaku tečka jako u struktury. V další části těchto stránek věnované objektově orientovanému programování se dozvíte, že toto je u tříd žádoucí přístup, tzv. princip zapouzdření.

Nyní je u tříd něco nového. Jsou uvnitř třídy definovány funkce nazývané metody. Jejich syntaxe je v podstatě stejná, jako u funkcí klasických, které jsme již popsali jen s jediným rozdílem, že se nachází uvnitř definice třídy ohraničené složenými závorkami.

První množina metod pracuje se jménem a příjmením. Metoda nastavJmeno nastaví atributy dle jejich argumentů a metody vratJmenovratPrijmeni zase hodnoty těchto atributů vrátí.

U atributu věk je to podobně. Metody nastavVek a vratVek, jak jejich název napovídá, slouží k nastavení a vrácení atributu věk zákazníka. Je zde ale ještě jedna metoda, zvysVek, která inkrementuje hodnotu příslušného atributu o jeden rok.

Posledním bodem u popisu deklarace třídy je “tajuplné slovíčko” public, na konci ukončené dvojtečkou. Toto klíčové slovo, umístěné před definicemi metod, mění výchozí oprávnění přístupu k položkám třídy na veřejný přístup, což znamená, že položky, které jsou za ním umístěné, mohou být volány klientskou třídou nebo funkcí. Na našem příkladu to jsou pouze příslušné metody. Více o tématu oprávnění u OOP se dovíte v další části těchto stránek.

Použití této třídy bude trochu jiné od struktury, jak ukazuje následující příklad:

#include <string>
#include <iostream>
using namespace std;

class Zakaznik {
    string jmeno;
    string prijmeni;
    int vek;
public:
    void nastavJmeno(const string& jm, const string& pr) { 
        jmeno = jm;
        prijmeni = pr;
    }

    const string& vratJmeno() { return jmeno; }
    const string& vratPrijmeni() { return prijmeni; }

    void nastavVek(int v) {
        vek = v;
    }
    int vratVek() { return vek; }

    void zvysVek() {
        vek = vek + 1;
    }
};

void printZakaznik(Zakaznik& z) {
    cout << "Jméno: " << z.vratJmeno() << " " << z.vratPrijmeni() << endl;
    cout << "Věk: " << z.vratVek() << endl << endl;
}

int main() {
    Zakaznik z;
    z.nastavJmeno("Michal", "Chaloupka");
    z.nastavVek(25);
    printZakaznik(z);
    
    z.zvysVek();
    printZakaznik(z);
    
    z.nastavJmeno("Ales", "Bures");
    z.zvysVek();
    printZakaznik(z);
    
    return 0;
}

 

Na příkladu je uvedena definice třídy z předchozího příkladu. Dále je možné vidět funkci printZakaznik, kam se předává třída referencí k vypsání informací o zákazníkovi na standardní výstup. Je si možné povšimnout, že metody třídy jsou volány stejným způsobem jako jsme přistupovali k položkám struktury. Napřed se uvede název konkrétní proměnné, po té znak “tečka” a následně je uveden název příslušné metody s argumenty v závorce. Mělo by být zřejmé, že práce se třídou by měla probíhat téměř vždy přes volání veřejných metod. Pokud potřebujeme pouze předávat složitější strukturu dat, měla by se zvolit forma definice uživatelského typu pomocí klíčového slova struct, u kterého je výchozí přístup k položkám veřejný.

image_printTisk
Strukturované datové typy
C++ 11
Ohodnoťte tento článek

Související články

  • Chytré ukazatele Často potřebujeme alokovat, či jinak řečeno si rezervovat, paměť na dynamické části paměti, jelikož neznáme potřebnou délku v době kompilace programu, ale až za jeho běhu. Například […]
  • Seznamy hodnot podrobněji V tomto článku se blíže seznámíme se seznamy hodnot. Máme na výběr dva typy seznamů. Seznam s pevným počtem položek nebo seznam s proměnlivým počtem položek. Seznam s pevným počtem […]
  • Datový typ “string” podrobněji Datový typ string nás provází od počátku studia jazyka C++ na těchto stránkách. V tomto článku se hlouběji seznámíme, jak funguje a co nám nabízí za funkce, které pro práci s textem můžeme […]
  • Organizace dat v paměti RAM Tento článek poskytuje teoretický úvod do způsobu uspořádání paměti aplikace. Seznámíme se s jednotlivými bloky paměti a jejich významem a dále bude výklad stručně doplněn o téma […]
  • Konstanty Tento článek si klade za cíl vysvětlit význam a princip fungování konstant v jazyce C++. Seznámíme se s důvody jejich zavedení, uvedu zde dvě formy jejich zápisu a krátce záměrně odbočím […]
  • Ukazatele na pole V tomto článku si probereme ukazatele na pole. Seznámíme se nejen s ukazateli na pole jednorozměrné, ale i na složitější případ, tedy pole vícerozměrná. Vše si zase samozřejmě uvedeme na […]