5. Zßklady OOP V
  1. Pokud jsme doposud v na╣ich programech pracovali se soubory, pak to bylo zp∙sobem, kter² se pou╛φval v jazyku C. Je nutno se takΘ seznßmit se Φtenφm a zßpisem soubor∙ pomocφ datov²ch proud∙. Zßkladnφ souborovΘ vstupn∞/v²stupnφ operace jsou v C++ provßd∞ny pomocφ t∞chto t°φd:
  2. Nßsledujφcφ jednoduchß konzolovß aplikace Φte sv∙j vlastnφ zdrojov² soubor a zobrazuje jej na obrazovce (program ulo╛φme do CTENISOUBORU.CPP). Pokud program ulo╛φme pod jin²m jmΘnem, pak nebude sprßvn∞ pracovat.
    #include <condefs.h>
    #include <fstream.h>
    #include <conio.h>
    #pragma hdrstop
    #pragma argsused
    int main(int argc, char **argv)
    {
      char buff[80];
      ifstream vstsoubor;
      vstsoubor.open("ctenisouboru.cpp");
      if (!vstsoubor) return 0;
      while (!vstsoubor.eof()){
        vstsoubor.getline(buff, sizeof(buff));
        cout << buff << endl;
      }
      vstsoubor.close();
      getch();
      return 0;
    }
    Na zaΦßtku programu vytvß°φme instanci t°φdy ifstream nazvanou vstsoubor. Na dal╣φm °ßdku otvφrßme nß╣ soubor pro vstup. Nßsleduje test ·sp∞╣nosti otev°enφ souboru (v p°φpad∞ ne·sp∞chu je program ukonΦen). Podmφnkou ukonΦenφ cyklu je volßnφ metody eof t°φdy ifstream. Tato metoda vracφ true p°i nalezenφ konce souboru. JednotlivΘ °ßdky souboru jsou Φteny metodou getline. Text °ßdku je umφst∞n do znakovΘho pole buff a potom je vypsßn na obrazovku. Po doΦtenφ souboru je soubor je╣t∞ uzav°en (metoda close). Pro pou╛φvßnφ t°φdy ifstream je nutno vlo╛it hlaviΦkov² soubor FSTREAM.H.
    Jeden z konstruktor∙ ifstream p°ebφrß jako parametr ukazazel na char a umo╛≥uje tak zadat jmΘno souboru p°i vytvß°enφ instance t°φdy. Pomocφ tohoto konstruktoru lze nahradit ΦervenΘ °ßdky z p°edchozφho programu nßsledujφcφm °ßdkem:
    ifstream vstsoubor("ctenisouboru.cpp");
    Kdy╛ vytvo°φme objekt tφmto zp∙sobem, pak pou╛itφ metody open ji╛ nenφ nutnΘ, nebo╗ soubor je automaticky otev°en konstruktorem. Nezapom∞≥te p°i zadßvßnφ specifikace souboru i s adresß°evou cestou nahrazovat znaky \ pomocφ \\.
    Uzav°enφ souboru nenφ nutnΘ. Destruktor ifstream testuje, zda soubor z∙stal otev°en a pokud ano, pak jej p°ed zru╣enφm instance t°φdy uzav°e. Pou╛φvßnφ close tedy nenφ vy╛adovßno. Pokud jej pou╛ijeme, pak tφm naznaΦujeme, ╛e soubor ji╛ dßle nenφ zapot°ebφ.
  3. V na╣em programu je malß chyba. Program vypφ╣e p°ed ukonΦenφm cyklu jeden prßzdn² °ßdek navφc. Abychom tuto chybu odstranili, musφme nß╣ cyklus zapsat takto:

  4. while (!vstsoubor.getline(buff, sizeof(buff)).eof()){
      cout << buff << endl;
    }
    Z°et∞zenφ metod je dovoleno, i kdy╛ nenφ moc pou╛φvßno. Jeho pou╛itφm zφskßme mΘn∞ srozumiteln² k≤d. Umo╛≥uje ale snadno odstranit n∞kterΘ chyby.
  5. Proto╛e t°φdy zpracovßvajφcφ soubory jsou odvozeny od iostream, m∙╛eme takΘ pou╛φvat operßtory vlo╛enφ a v²b∞ru do/z datovΘho proudu a to stejn∞ jako u datov²ch proud∙ cin a cout. V na╣em programu jsme pou╛ili getline, proto╛e >> ukonΦφ Φtenφ po nalezenφ prvnφ mezery (nebo od°ßdkovßnφ).

  6. Operßtor >> je v²hodn² p°i Φtenφ jednotliv²ch hodnot. Nap°. nßsledujφcφ Φßst programu Φte celß Φφsla ze souboru a zobrazuje je na obrazovce.
    ifstream vstsoubor("nejakysoubor.dat");
    while (!vstsoubor.eof()){
      int x;
      vstsoubor >> x;
      cout << x << endl;
    }
    Operßtor v²b∞ru z proudu Φte data z textovΘho souboru ale ne z binßrnφho souboru. Tento operßtor Φte text ze souboru a p°evßdφ jej na Φφslo.
  7. Vytvß°enφ soubor∙ je snadn∞j╣φ ne╛ jejich Φtenφ. Namφsto vytvo°enφ instance t°φdy ifstream, vytvo°φme instanci t°φdy ofstream a pro zßpis do souboru pou╛φvßme operßtor vlo╛enφ do proudu. Nap°.

  8. ofstream vystsoubor("Test.dat");
    if (!vystsoubor) return 0;
    for (int i = 0; i < 10; i++) {
      vystsoubor << "Toto je °ßdek " << (i + 1) << endl;
    }
    vystsoubor.close();
  9. Vytvo°te konzolovou aplikaci, kterß bude p°ebφrat vstup od u╛ivatele a zapφ╣e jej do textovΘho souboru.

  10. Modifikujte p°edchozφ zadßnφ tak, ╛e na zßv∞r vytvo°en² soubor op∞t p°eΦtete a vypφ╣ete na obrazovku. V tomto p°φpad∞ musφme, p°ed otev°enφm souboru pro Φtenφ, zapsan² soubor uzav°φt.
  11. V C++ je mo╛no d∞dit p°i vytvß°enφ novΘ t°φdy metody a datovΘ slo╛ky od dvou nebo vφce t°φd p°edk∙. Toto se oznaΦuje jako vφcenßsobnß d∞diΦnost. Vφcenßsobnß d∞diΦnost je ukßzßna v nßsledujφcφm programu.

  12. class dodavka {
      protected:
      float naklad;
      float vaha_objektu;
      float spotreba;
    public:
      void inicializace(float na, float va, float sp){
        naklad = na;
        vaha_objektu = va;
        spotreba = sp;
      }
      float ucinnost(void){
        return (naklad / (naklad + vaha_objektu));
      }
      float naklady_na_tunu(float cena_paliva){
        return (cena_paliva / (naklad / 2000.0));
      }
    };
    class ridic {
    protected:
      float hod_mzda;
    public:
      void inicializace(float mzda){hod_mzda = mzda; }
      float naklady_na_km(void) {return (hod_mzda / 90.0); }
    };
    class rizene_auto : public dodavka, public ridic {
    public:
      void celk_inicializace(float na, float va, float sp, float mzda){
        naklad = na;
        vaha_objektu = va;
        spotreba = sp;
        hod_mzda = mzda;
      }
      float naklady_na_cely_den(float naklady_na_palivo){
        return (8.0 * hod_mzda +
                8.0 * naklady_na_palivo * 90.0 / spotreba);
      }
    };
    int main(int argc, char **argv)
    {
      rizene_auto novak_ford;
      novak_ford.celk_inicializace(5000.0, 3000.0, 8.3, 76.5);
      cout << "┌Φinnost Fordu je " << novak_ford.ucinnost() << endl;
      cout << "Nßklady na km pro °idiΦe Novßka jsou " <<
               novak_ford.naklady_na_km() << endl;
      cout << "Nßklady na °φzenφ Fordu °idiΦem Novßkem jsou na den " <<
               novak_ford.naklady_na_cely_den(20.0) << endl;
      return 0;
    }
    Pro zjednodu╣enφ hledßnφ k≤du v tomto programu jsou v╣echny metody implementovßny jako vno°enΘ. V╣echny slo╛ky t°φd jsou deklarovßny jako chrßn∞nΘ a jsou tedy p°φstupnΘ v odvozen²ch t°φdßch. K≤d pro v╣echny t°φdy je velmi jednoduch², nebo╗ se zam∞°ujeme hlavn∞ na studium d∞diΦnosti. Na ΦervenΘm °ßdku deklarujeme t°φdu rizene_auto, kterß d∞dφ v╣echna data a metody od obou d°φve definovan²ch t°φd. P°i vφcenßsobnΘ d∞diΦnosti zapisujeme za klφΦovΘ slovo public (p°φpadn∞ jinΘ p°φstupovΘ specifikßtory) jmΘna v╣ech t°φd p°edk∙. V tomto p°φpad∞ nedefinujeme v odvozenΘ t°φd∞ ╛ßdnΘ novΘ datovΘ slo╛ky, ale p°idßvßme do nφ dv∞ novΘ metody.
    V hlavnφm programu deklarujeme objekt novak_ford, kter² popisuje n∞jakΘho Novßka °φdφcφho dodßvku Ford. Tento objekt se sklßdß ze Φty° datov²ch slo╛ek z nich╛ t°i pochßzejφ od t°φdy dodavka a jedna od t°φdy ridic. Se v╣emi t∞mito Φty°mi slo╛kami m∙╛eme pracovat ve v╣ech metodßch t°φdy rizene_auto a to stejn∞ jako p°i jednoduchΘ d∞diΦnosti. V╣echna pravidla platφcφ pro jednoduchou d∞diΦnost platφ i pro vφcenßsobnou d∞diΦnost. V hlavnφm programu jsme nedeklarovali ╛ßdn² objekt t°φd p°edk∙. Pou╛ily bychom je normßlnφm zp∙sobem. V na╣em programu je v obou t°φdßch p°edk∙ deklarovßna metoda inicializace. Zjist∞te, kterß z nich se pou╛ije, za╣leme-li objektu novak_ford zprßvu inicializace.
  13. V nßsledujφcφ verzi programu jsou ve v╣ech t°φdßch metody naklady_na_cely_den. Tento program ukazuje jak pou╛φvat tyto stejnojmennΘ metody a jak urΦit, kterou z nich chceme pou╛φt. Program si prostudujte.

  14. class dodavka {
    protected:
      float naklad;
      float vaha_objektu;
      float spotreba;
    public:
      void inicializace(float na, float va, float sp){
        naklad = na;
        vaha_objektu = va;
        spotreba = sp;
      }
      float ucinnost(void){
        return (naklad / (naklad + vaha_objektu));
      }
      float naklady_na_tunu(float cena_paliva){
        return (cena_paliva / (naklad / 2000.0));
      }
      float naklady_na_cely_den(float naklady_na_palivo){
        return (8.0 * naklady_na_palivo * 90.0 / spotreba);
      }
    };
    class ridic {
    protected:
      float hod_mzda;
    public:
      void inicializace(float mzda){hod_mzda = mzda; }
      float naklady_na_km(void) {return (hod_mzda / 90.0); }
      float naklady_na_cely_den(float prescas_mzda){
        return (8.0 * hod_mzda);
      }
    };
    class rizene_auto : public dodavka, public ridic {
    public:
      void celk_inicializace(float na, float va, float sp, float mzda){
        naklad = na;
        vaha_objektu = va;
        spotreba = sp;
        hod_mzda = mzda;
      }
      float naklady_na_cely_den(float naklady_na_palivo){
        return (8.0 * hod_mzda +
          8.0 * naklady_na_palivo * 90.0 / spotreba);
      }
    };
    int main(int argc, char **argv)
    {
      rizene_auto novak_ford;
      novak_ford.celk_inicializace(5000.0, 3000.0, 8.3, 76.5);
      cout << "┌Φinnost Fordu je " << novak_ford.ucinnost() << endl;
      cout << "Nßklady na km pro °idiΦe Novßka jsou " <<
        novak_ford.naklady_na_km() << endl;
      cout << "Nßklady na Ford jsou na den " <<
       novak_ford.dodavka::naklady_na_cely_den(20.0) << endl;
      cout << "Nßklady na °idiΦe Novßka jsou na den " <<
       novak_ford.ridic::naklady_na_cely_den(95.0) << endl;
      cout << "Nßklady na °φzenφ Fordu °idiΦem Novßkem jsou na den " <<
       novak_ford.naklady_na_cely_den(20.0) << endl;
      return 0;
    }
  15. V dal╣φ ukßzce se pou╛φvß u obou t°φd p°edk∙ datovß slo╛ka se jmΘnem vaha_objektu. Objekt t°φdy rizene_auto tedy d∞dφ dv∞ slo╛ky stejnΘho jmΘna. Prostudujte si v tomto programu, jak se takovΘto slo╛ky pou╛φvajφ.

  16. class dodavka {
    protected:
      float naklad;
      float vaha_objektu;
      float spotreba;
    public:
      void inicializace(float na, float va, float sp){
        naklad = na;
        vaha_objektu = va;
        spotreba = sp;
      }
      float ucinnost(void){
        return (naklad / (naklad + vaha_objektu));
      }
      float naklady_na_tunu(float cena_paliva){
        return (cena_paliva / (naklad / 2000.0));
      }
    };
    class ridic {
    protected:
      float hod_mzda;
      float vaha_objektu;
    public:
      void inicializace(float mzda, float vaha){
        hod_mzda = mzda;
        vaha_objektu = vaha;
      }
      float naklady_na_km(void) {return (hod_mzda / 90.0); }
      float vaha_ridice(void) {return (vaha_objektu);}
    };
    class rizene_auto : public dodavka, public ridic {
    public:
      void celk_inicializace(float na, float va, float sp, float mzda){
        naklad = na;
        dodavka::vaha_objektu = va;
        spotreba = sp;
        hod_mzda = mzda;
      }
      float naklady_na_cely_den(float naklady_na_palivo){
        return (8.0 * hod_mzda +
                8.0 * naklady_na_palivo * 90.0 / spotreba);
        }
      float celkova_vaha(void){
        return (dodavka::vaha_objektu + ridic::vaha_objektu);
      }
    };
    int main(int argc, char **argv)
    {
      rizene_auto novak_ford;
      novak_ford.celk_inicializace(5000.0, 3000.0, 8.3, 76.5);
      novak_ford.ridic::inicializace(80.0, 85.0);
      cout << "UΦinnost Fordu je " << novak_ford.ucinnost() << endl;
      cout << "Nßklady na km pro °idiΦe Novßka jsou " <<
               novak_ford.naklady_na_km() << endl;
      cout << "Nßklady na °φzenφ Fordu °idiΦem Novßkem jsou na den " <<
               novak_ford.naklady_na_cely_den(20.0) << endl;
      cout << "Celkovß vßha je " << novak_ford.celkova_vaha() << endl;
      return 0;
    }
    Proto╛e Object Pascal neznß vφcenßsobnou d∞diΦnost, nelze pou╛φvat vφcenßsobnou d∞diΦnost ve t°φdßch odvozen²ch od t°φd VCL (t°φd knihovny vizußlnφch komponent; knihovna je naprogramovanß v Object Pascalu). Vφcenßsobnou d∞diΦnost lze tedy pou╛φvat pouze mimo rßmec VCL.
5. Zßklady OOP V