19. DynamickΘ prom∞nnΘ
  1. Nßsledujφcφ Φßst programu p°eΦte textov² soubor a °ßdky textu ulo╛φ v operaΦnφ pam∞ti. P°edpoklßdßme, ╛e soubor obsahuje maximßln∞ 1000 °ßdk∙ textu (°ßdky textu nebudou del╣φ ne╛ 99 znak∙) a pro ulo╛enφ °ßdku rezervujeme pouze pot°ebn² poΦet slabik. Na zßv∞r programu jsou pou╛itΘ dynamickΘ prom∞nnΘ uvoln∞ny.

  2. char radek[100];
    char *radky[1000];
    FILE *soubor;
    int i, n = 0;
    if ((soubor = fopen("SOUBOR.TXT", "rt")) == NULL) {
      cout << "Soubor nelze otev°φt" << endl;
      return 1;
    }
    while (fgets(radek, sizeof(radek), soubor) != NULL) {
      radky[n] = new char[strlen(radek) + 1];
      strcpy(radky[n++], radek);
    }
    for (i = 0; i < n; i++) delete[] radky[i];
    Zm∞≥te tento program tak, aby bylo mo╛no specifikovat Φten² soubor a aby obsah souboru ulo╛en² v pam∞ti byl vypsßn na obrazovku.
  3. V p°edchozφm zadßnφ jsme pro ulo╛enφ ukazatel∙ na jednotlivΘ °ßdky textu pou╛ili statickΘ pole (velikost pole je v na╣em p°φpad∞ omezena na 1000 °ßdk∙). Abychom toto omezenφ obe╣li pou╛ijeme spojov² seznam s prvky

  4. struct prvek {
      prvek *dalsi;
      char radek[100];
    }
    Polo╛ka dalsi ukazuje na dal╣φ prvek seznamu (dal╣φ °ßdek textu) a polo╛ka radek obsahuje vlastnφ text °ßdku. Abychom se spojov²m seznamem mohli pracovat, musφme mφt statickou prom∞nnou, kterß ukazuje na zaΦßtek seznamu. Jeliko╛ nov∞ p°eΦtenΘ °ßdky p°idßvßme na konec seznamu je vhodnΘ mφt i ukazatel na konec seznamu.
    Nßsleduje Φßst programu vytvß°ejφcφ spojov² seznam °ßdk∙ a Φßst uvol≥ujφcφ seznam.
    char radek[100];
    struct prvek {
      prvek *dalsi;
      char radek[100];
    } *zacatek = NULL, *konec, *pom;
    FILE *soubor;
    if ((soubor = fopen("SOUBOR.TXT", "rt")) == NULL) {
      cout << "Soubor nelze otev°φt" << endl;
      return 1;
    }
    while (fgets(radek, sizeof(radek), soubor) != NULL) {
      pom = (prvek *)new char[strlen(radek)+sizeof(prvek *) + 1];
      strcpy(pom->radek, radek);
      if (zacatek == NULL) zacatek = pom;
        else konec->dalsi = pom;
      konec = pom;
      konec->dalsi = NULL;
    }

    while (zacatek->dalsi != NULL) {
      pom = zacatek;
      zacatek = zacatek->dalsi;
      delete[] pom;
    }
    Dopl≥te tento program o v²pis v pam∞ti ulo╛enΘho obsahu souboru.


  5. C++ umo╛≥uje pracovat s funkcemi, kterΘ majφ stejnΘ jmΘno ale r∙znΘ parametry. Funkce, kterΘ sdφlejφ spoleΦnΘ jmΘno, se naz²vajφ p°ekrytΘ funkce. P°edpoklßdejme, ╛e mßme funkci nasob, kterß nßsobφ dva celoΦφselnΘ parametry a vracφ v²sledek nßsobenφ. M∙╛eme ale takΘ pot°ebovat podobnou funkci, kterß nßsobφ dv∞ reßlnß Φφsla. V C bylo nutno pou╛φvat r∙znΘ funkce:

  6. int nasobInt(int cislo1, int cislo2);
    float nasobFloat(float cislo1, float cislo2);
    short nasobShort(short cislo1, short cislo2);
    V C++ ale m∙╛eme pracovat s p°ekr²vajφcφmi se funkcemi. Na╣e funkce tedy budou mφt tyto prototypy:
    int nasob(int cislo1, int cislo2);
    float nasob(float cislo1, float cislo2);
    short nasob(short cislo1, short cislo2);
    V╣echny funkce majφ stejnΘ jmΘno. P°ekladaΦ pak urΦφ volanou funkci na zßklad∞ p°edan²ch parametr∙. Nap°.
    float x = 1.5;
    float y = 17.2;
    float vysledek = nasob(x, y);
    P°ekladaΦ vidφ dva parametry typu float, kterΘ jsou p°edßvßny funkci nasob a volß funkci nasob s dv∞ma parametry typu float. Pokud parametry budou typu int, pak bude pou╛ita verze funkce s parametry typu int.
    Volanß funkce je tedy urΦena seznamem parametr∙ (ka╛dß deklarace p°ekr²vajφcφ funkce musφ mφt jin² seznam parametr∙; tj. poΦet parametr∙ a typy parametr∙). Nelze vytvo°it p°ekrytΘ funkce, kterΘ se budou li╣it pouze vrßcenou hodnotou.
    P°ekladaΦ rozli╣uje p°ekrytΘ funkce pomocφ procesu nazvanΘho komolenφ jmen. Komolenφ jmen spoΦφvß v zak≤dovßnφ poΦtu a typu parametr∙ v internφm jmΘn∞ funkce, kterΘ je udr╛ovßno p°ekladaΦem.
  7. Pou╛φvßnφ p°ekryt²ch funkcφ vy╛aduje pou╛itφ sprßvn²ch datov²ch typ∙ p°i volßnφ funkce. P°i p°evodu datovΘho typu pou╛φvßme p°etypovßnφ, tj. p°evod jednoho datovΘho typu na jin². Nap°.

  8. float x = (float)10 * 5.5;
    V tomto p°φpad∞ p°etypovßnφ °φkß p°ekladaΦi "ud∞lej z Φφsla 10 typ float". Druh² operand je automaticky interpretovßn jako typ float, proto╛e obsahuje desetinnou teΦku. Podφvejte se je╣t∞ na nßsledujφcφ p°φklad:
    int cele = 5;
    float realne = 10.5;
    float vysledek = nasob(cele, realne);
    V tomto p°φpad∞ p°ekladaΦ generuje chybu, proto╛e nem∙╛e nalΘzt funkci nasob s prvnφm parametem typu int a druh²m parametrem typu float. Podobnou chybu bude generovat i v p°φpad∞ p°φkazu:
    int vysledek = nasob(10, 10);
    Zde p°ekladaΦ nedokß╛e urΦit jakΘho typu jsou pou╛itΘ ΦφselnΘ konstanty. V tΘto situaci mßme dv∞ mo╛nosti. Konstanty p°ed volßnφm funkce p°i°adφme do prom∞nn²ch nebo provedeme p°i volßnφ p°etypovßnφ. Prvnφ mo╛nost ukazuje nßsledujφcφ k≤d:
    int x = 10;
    int y = 10;
    int vysledek = nasob(x, y);
    a druhou mo╛nost k≤d:
    int vysledek = nasob((int)10, (int)10);
    Nynφ p°ekladaΦ vφ, ╛e mß tyto konstanty brßt jako typ int. P°etypovßnφ lze takΘ pou╛φt k doΦasnΘ zm∞n∞ jednoho datovΘho typu na jin². Nap°.
    int cele = 5;
    float realne = 10.5;
    float vysledek = nasob((float)cele, realne);
    V tomto p°φpad∞ je prvnφ parametr p°eveden na typ float a p°ekladaΦ je ji╛ schopen najφt po╛adovanou funkci.
  9. Funkce implementujφcφ implicitnφ parametry m∙╛e vypadat takto:

  10. // deklarace - parametr "poprve" mß implicitnφ hodnotu false
    void Redraw(bool poprve = false);
    // definice
    void Redraw(bool poprve)
    {
      if (poprve){
        // k≤d pro prvnφ kreslenφ
      }
      // k≤d kreslenφ
    }
    Tuto funkci m∙╛eme volat s nebo bez parametru. Pokud je p°i volßnφ funkce parametr uveden, pak funkce se chovß jako normßlnφ funkce. Pokud p°i volßnφ funkce parametr nenφ uveden, pak je automaticky pou╛ita implicitnφ hodnota parametru. Pro nß╣ p°φklad jsou nßsledujφcφ dva °ßdky k≤du identickΘ:
    Redraw();
    Redraw(false);
    Kdy╛ parametr mß implicitnφ hodnotu, pak p°i volßnφ funkce m∙╛e b²t vynechßn. V jednΘ funkci mohou b²t takΘ implicitnφ i neimplicitnφ parametry:
    int PlaySound(char* name, bool loop = false, int loops = 10);
    // volßnφ funkce
    int vysl;
    vysl = PlaySound("chime.wav");
    vysl = PlaySound("ding.wav", true);
    vysl = PlaySound("bell.wave", true, 5);
    Implicitnφ parametry jsou z mnoha d∙vod∙ u╛iteΦnΘ. Pokud p°i volßnφ n∞kterΘ funkce pou╛φvßme Φasto stejnΘ parametry, pak pou╛itφ implicitnφch parametr∙ nßm usnadnφ prßci.
    Implicitnφ parametry musφme uvßd∞t na konci seznamu parametr∙. Nßsledujφcφ deklarace funkce je chybnß:
    int mojeFunkce(int x, int y = 10, int t = 5, int z);
    Implicitnφ parametry musφme p°esunout na konec seznamu parametr∙:
    int mojeFunkce(int x, int z, int y = 10, int t = 5);
  11. Metody (ΦlenskΘ funkce t°φdy) se pou╛φvajφ stejn∞ jako normßlnφ funkce. Mohou b²t p°ekrytΘ, mohou mφt implicitnφ parametry atd. Metody mohou b²t volßny pouze prost°ednictvφm objekt∙ t°φdy, do kterΘ metoda pat°φ. K volßnφ metody pou╛φvßme p°φm² nebo nep°φm² selektor slo╛ky. Nap°. mßme t°φdu nazvanou Letadlo, kterou budeme pou╛φvat v simulaΦnφm programu letadla. Tato t°φda pravd∞podobn∞ bude mφt mo╛nost zφskat souΦasnou rychlost danΘho letadla pomocφ metody nazvanΘ ziskejRychlost. Nßsledujφcφ p°φklad ukazuje, jak volßme tuto metodu objektu Letadlo:

  12. Letadlo sokol;    // vytvo°enφ instance t°φdy
    int rychlost = sokol.ziskejRychlost();
    cout << "SouΦasnß rychlost letadla je " << rychlost << endl;
    Tento k≤d pou╛φvß k volßnφ funkce ziskejRychlost operßtor p°φmΘho selektoru slo╛ky. Metody definujeme podobn∞ jako normßlnφ funkce, je zde zapot°ebφ navφc uvΘst jmΘno t°φdy a operßtor ::. Nap°. definice na╣φ metody m∙╛e vypadat takto:
    int Letadlo::zφskejRychlost()
    {
      return rychlost;    // rychlost je datovß slo╛ka t°φdy
    }
    Operßtor :: °φkß p°ekladaΦi, ╛e funkce zφskejRychlost je metodou t°φdy Letadlo. Vφce o t°φdßch a metodßch se dozvφme pozd∞ji.
  13. Normßln∞ strojov² k≤d funkce se v p°elo╛enΘm proveditelnΘm k≤du vyskytuje pouze jednou. P°i volßnφ funkce je proveden skok na vstupnφ bod funkce a p°i ukonΦenφ funkce se op∞t vrßtφme na mφsto volßnφ funkce. Existujφ takΘ vlo╛enΘ (inline) funkce, kde k≤d funkce je vlo╛en do proveditelnΘho k≤du programu na mφsto volßnφ funkce. Vlo╛enΘ funkce se deklarujφ podobn∞ jako normßlnφ funkce, ale jejich definice zaΦφnß klφΦov²m slovem inline. Poka╛dΘ, kdy╛ p°ekladaΦ ve zdrojovΘm k≤du nalezne volßnφ vlo╛enΘ funkce, pak umφstφ separßtnφ kopii k≤du funkce na toto mφsto do p°elo╛enΘho programu. Vlo╛enΘ funkce pracujφ rychle, proto╛e nenφ zapot°ebφ provßd∞t volßnφ funkce.

  14. Je vhodnΘ, aby vlo╛enΘ funkce byly velmi malΘ. Del╣φ funkce nenφ vhodnΘ pou╛φvat jako vlo╛enΘ, nebo╗ v²sledkem je zv∞t╣enφ p°elo╛enΘho spustitelnΘho programu.
    Vlo╛enΘ funkce jsou obvykle metody. ╚asto definici vlo╛enΘ funkce umis╗ujeme do hlaviΦkovΘho souboru deklarace t°φdy. Metoda ziskejRychlost z p°edchozφho zadßnφ je krßtkß a je tedy mo╛no z nφ ud∞lat vlo╛enou funkci. To provedeme takto:
    inline int Letadlo::zφskejRychlost()
    {
      return rychlost;    // rychlost je datovß slo╛ka t°φdy
    }

NovΘ pojmy:

Kontrolnφ otßzky:

  1. Musφme v╛dy zru╣it objekt, kter² byl vytvo°en dynamicky pomocφ operßtoru new?
  2. Kdy vytvß°φme objekty v zßsobnφku a kdy v hromad∞?
  3. Co to jsou p°ekrytΘ funkce?
  4. Kdy pou╛φvßme vlo╛enΘ funkce?
  5. Co je to ukazatel?
  6. Co d∞lß dereference ukazatele?
  7. Co je vrßcenß hodnota operßtoru new?
  8. Lze instance t°φd a struktur p°edßvat funkcφm odkazem nebo hodnotou?
  9. Co d∞lß klφΦovΘ slovo const?
  10. Vytvß°ejφ nßsledujφcφ deklarace p°ekrytΘ funkce?

  11. void mojeFunkce(int x);
    int mojeFunkce(int x);
  12. Je lep╣φ pou╛φvat odkazy nebo ukazatele?
  13. Co je metoda?
  14. Jak se li╣φ zachßzenφ p°ekladaΦe s vlo╛enou funkcφ od normßlnφ funkce?
  15. Co je chybnΘ na nßsledujφcφ ukßzce?

  16. char* buff = new char[200];
    // a pozd∞ji
    delete buff;
╪e╣enφ


19. DynamickΘ prom∞nnΘ