IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

8. diel - Konštantný metódy v C ++

V minulej lekcii, Aréna s bojovníkmi v C ++ , sme dokončili našu objektovú arénu. V dnešnom tutoriále zistíme, čo sú to konštantné metódy a prečo sa nimi zaoberať.

Konštantný metódy

Ako už názov napovedá, konštantný metóda je taká metóda, ktorá nemení dáta inštancie. Sú to všetky Getter - iba získavajú dáta, nič nemení. Z toho dôvodu by správne mali byť všetky Getter označené ako konštantná. Metóda Bojovnik.nazivu() je tiež svojím spôsobom getter, pretože iba zisťuje či je dostatočný počet životov. Všetky metódy, ktoré nemenia dáta, by sme mali označiť ako konštantná - to urobíme jednoducho pridaním kľúčového slova const za názov metódy (do .hi .cpp súboru). Napríklad pre triedu Bojovnik:

Bojovnik.h

#ifndef __BOJOVNIK_H_
#define __BOJOVNIK_H_
#include <string>
#include "Kostka.h"

using namespace std;

class Bojovnik
{
private:
    float zivot;
    float max_zivot;
    float utok;
    float obrana;
    Kostka &kostka;
public:
    Bojovnik(float zivot, float utok, float obrana, Kostka &kostka);
    bool nazivu() const;
    float utoc(Bojovnik &druhy) const;
    float getZivot() const;
    float getMaxZivot() const;
    float getUtok() const;
    float getObrana() const;
};
#endif

Bojovnik.cpp

#include "Bojovnik.h"

Bojovnik::Bojovnik(float zivot, float utok, float obrana, Kostka &kostka) :
    kostka(kostka), zivot(zivot), max_zivot(zivot), utok(utok), obrana(obrana)
{}

bool Bojovnik::nazivu() const
{
    return this->zivot > 0;
}

float Bojovnik::utoc(Bojovnik & druhy) const
{
    float obrana_druhy = druhy.obrana + druhy.kostka.hod();
    float utok_prvni = this->utok + this->kostka.hod();
    float zraneni = utok_prvni - obrana_druhy;
    if (zraneni < 0)
        zraneni = 0;
    druhy.zivot -= zraneni;
    return zraneni;
}

float Bojovnik::getZivot() const
{
    return this->zivot;
}

float Bojovnik::getMaxZivot() const
{
    return this->max_zivot;
}

float Bojovnik::getUtok() const
{
    return this->utok;
}

float Bojovnik::getObrana() const
{
    return this->obrana;
}

Všimnite si, že aj metóda utoc() je konštantná - nemení dáta inštancie, ale mení dáta parametra.

Pravidlá

Prečo sa tým zaoberáme? Kľúčové slovo const nám postráži, že je metóda správne implementovaná. Ak by sme pre triedu Kocka nadefinovali metódu setPocetSten() a nastavili ju ako konštantná, kompilátor by nám zahlásil nasledujúce hlášku (pre Visual Studio):

error C2228: left of '.pocet_sten' must have class/struct/union
note: type is 'const Kostka *const '
note: did you intend to use '->' instead?

Kompilátor si sám postráži, že funkcia nemôže nič zmeniť a ostatné programátorov tým informujeme, že dáta sú v bezpečí (nemôžu sa zmeniť).

Aké ďalšie pravidlá platia? Z konštantný metódy môžeme volať iba konštantný metódy. To znamená, že vo chvíli, keď nastavíme getter ako konštantná, nemôžeme z neho zavolať setter (inak by kľúčové slovo const nedávalo zmysel - modifikovala by sa dáta).

Existuje ešte tretí a najdôležitejšie pravidlo: na konštantnej objekty možno volať iba konštantný metódy. Napríklad pre nášho bojovníka. Predpokladáme, že nasledujúci kód by mal fungovať:

const Bojovnik bojovnik(100,8,5,kostka);
float utok = bojovnik.getUtok();
float obrana = bojovnik.getObrana();
float uroven_agresivity = utok - obrana;

Prečo by sme to očakávali? Hoci je bojovník konštantná, chceme získať útok a obranu iba pre čítanie - to by nemal byť problém, pretože metódy nemení dáta a konštanta je dodržaná. To ale viete vy, ale zatiaľ to nevie kompiler. Aby tento kód fungovať, musíte nastaviť Getter ako konštantná - kompiler má potom istotu, že metóda nič nezmení a môže byť teda volaná nad konštantným objektom.

Ukazovatele

Pre ukazovatele a referencie sa situácia ešte trochu skomplikuje. Pridaním kľúčového slova const za názov metódy sa stane, že sú (pre predstavu) všetky atribúty označené ako konštantná. Pre ukážku si predstavme nasledujúce triedu:

class Uzivatel
{
    int vek;
    char* jmeno;
    void vypisJmeno() const;
};

Vnútri metódy vypisJmeno() bude vďaka const ukazovateľ this typu Uzivatel const * const (na rozdiel od klasického Uzivatel * const). Len pre upresnenie, ukazovatele vždy čítame odzadu, teda Uzivatel const * const je "konštantný ukazovateľ na konštantného užívateľa", zatiaľ čo Uzivatel * const je "konštantný ukazovateľ na používateľa". Tiež máme dve možnosti zápisu, teda nasledujúce dve ukážky sú ekvivalentné: Uzivatel const * a const Uzivatel *.

Konštantná metódu si možno teda predstaviť tak, že všetky atribúty budú konštantný:

class Uzivatel
{
    const int vek;
    char * const jmeno;
};

Všimnite si typu atribútu jmeno. Jedná sa o konštantný ukazovateľ (nemôžeme zmeniť adresu, kam ukazuje), ale nie je to ukazovateľ na konštantnú hodnotu - meno môžeme stále zmeniť. Konštantná metódy nám nezaručí, že sa nezmení dáta inštancie - zaručí nám len to, že sa nezmení atribúty.

Na problémy dôjde aj pri práci s referenciami. Predstavme si, že chceme vrátiť vek používateľa referencií. Nie je to obvyklé, ale z nejakého dôvodu to tak chceme. Referenciu na int použiť nemôžeme, pretože typ atribútu je const int a typy sa musí zhodovať. Z toho vyplýva, že musíme použiť konštantný referenciu:

class Uzivatel
{
    int vek;
    char* jmeno;
    void vypisJmeno() const;
    const int& getVek() const;
};

Teraz by naše časť kódu fungovala, a keď sa nad tým zamyslíme, potom až teraz funguje správne - rešpektuje konštantné hodnoty tam, kde to dáva zmysel.

To by bolo pre dnešné kratšie lekciu všetko. V zdrojovom boli pridané konštanty ku getterům a k pár ďalším metódam (u ktorých to dávalo zmysel). Nabudúce budeme s kódom pokračovať a preto by som odporučil stiahnuť si zdrojové kódy dole pod článkom. Budete mať istotu, že budeme pracovať s rovnakým zdrojovým kódom. Nabudúce, v lekcii Riešené úlohy k 6. až 8. lekciu OOP v C ++ , nás čaká statika.

V nasledujúcom cvičení, Riešené úlohy k 6. až 8. lekciu OOP v C ++, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 75x (9.78 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C++

 

Predchádzajúci článok
Aréna s bojovníkmi v C ++
Všetky články v sekcii
Objektovo orientované programovanie v C ++
Preskočiť článok
(neodporúčame)
Riešené úlohy k 6. až 8. lekciu OOP v C ++
Článok pre vás napísal Patrik Valkovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity