1 / 56

Olio-ohjelmoinnin perusteet luento 2

Olio-ohjelmoinnin perusteet luento 2. Päivi Ovaska LTKK/Tietotekniikan osasto. Sisältö. Yleistä olio-ohjelmoinnista Olio-ohjelmoinnin osat Luokat ja kapselointi Luokkien muodostaminen Luokkien tuhoaminen. Yleistä olio-ohjelmoinnista.

pier
Download Presentation

Olio-ohjelmoinnin perusteet luento 2

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Olio-ohjelmoinnin perusteetluento 2 Päivi Ovaska LTKK/Tietotekniikan osasto

  2. Sisältö • Yleistä olio-ohjelmoinnista • Olio-ohjelmoinnin osat • Luokat ja kapselointi • Luokkien muodostaminen • Luokkien tuhoaminen

  3. Yleistä olio-ohjelmoinnista • Olio-ohjelmointi tapa ajatella ja suunnitella ohjelma, ei vain oliokielen kayttamista • Oliokieli ei takaa olioajattelua • Olio-ohjelmointi mahdollista muulla kuin oliokielella • (Yksi) ero ”perinteiseen ohjelmointiin”: • Perinteinen: painopiste tietorakenteissa ja algoritmeissa • Oliot: painopiste ongelman jakamisessa osakokonaisuuksiin, joilla omat vastuunsa ja jotka kommunikoivat keskenään • Sopii hyvin sekä top-down että bottom-up -suunnitteluun • Olennaista suunniteltavan järjestelmän käyttäytymisen ymmärtäminen

  4. Suurten ohjelmistokokonaisuuksien hallinta • Ongelman jakaminen yhden ihmisen hallittaviin paloihin ja yksinkertaistaminen abstrahoimalla • Abstraktio: Ajatustoiminta, jonka avulla jostakin käsitteestä saadaan yleisempi käsite vähentämällä siitä tiettyjä ominaisuuksia. Myös valikointi, jossa jokin ominaisuus tai ominaisuusryhmä erotetaan muista yhteyksistään tarkastelun kohteeksi • Abstrahoida: Suorittaa abstraktio, erottaa mielessään olennainen muusta yhteydestä • Abstrakti: Abstrahoimalla saatu, puhtaasti ajatuksellinen, käsitteellinen

  5. Esimerkki abstraktiosta • “Tiedon tallentaminen massamuistilaitteelle” • Sovellusohjelmoijan ei tarvitse tuntea kiintolevyn valmistajan käyttämää laitteen ohjauksen protokollaa, koodausta, ajoitusta ja bittien järjestystä, vaan hän voi käyttää erikseen määriteltyjä korkeamman(abstraktio) tason operaatioita (open, write, close)

  6. Oliopohjainen logiikka • Ohjelmiston ylimmän tason logiikka voidaan määritellä olioiden rajapintojen ja olioiden välisen kommunikaation avulla • Esimerkki: • Shakkinappulaolio pyytää shakkilautaa mallintavalta oliolta tietoa siitä, voiko se siirtyä määrättyyn ruutuun. Kyselyn seurauksena lautaolio voi taas vuorostaan kysyä muilta nappuloilta niiden nykyisiä paikkoja jne. Shakkilaudan logiikka UML sekvenssikaaviona

  7. Oliot ja luokat • Olio on itse vastuussa omien tietojensa käsittelystä omien toimenpiteidensä avulla • Oliot ryhmitellään luokkiin • Luokka määrittelee, mitä tietoja olioilla on ja mitä toimintoja luokan oliot osaavat • Oliot suorittavat näitä toimintoja saadessaan toisilta olioilta palvelupyyntöjä • Tietojen ja toimintojen yhdistämisellä pyritään helpottamaan ohjelmiston osien ylläpidettävyyttä ja uudelleenkäytettävyyttä • Luokat ovat uudelleenkäytettäviä komponentteja

  8. Olio-ohjelmoinnin näkökulmat • valmiiden luokkien hyödyntäminen • Valmiiden luokkien hyödyntäminen tarkoittaa luokkakirjaston käyttöä. Valmiita luokkia käyttäessään ohjelmoija voi luoda olioita luokkiin ja käyttää olioita pyytämällä niiltä palvelua. Ohjelmoijan on siis tunnettava luokkakirjaston luokkarakenne ja kunkin luokan vastuulla oleva palvelut. • uudelleenkäytettävien luokkien tuottaminen • Uudelleenkäytettävien luokkien tuottaminen tarkoittaa luokkakirjaston rakentamista ja täydentämistä. Tällöin olemassaolevia komponentteja voidaan koota valmiista testatuista komponenteista tuottamalla mahdollisimman vähän uutta ohjelmakoodia.

  9. Oliot ja komponentit • Oliokeskeinen ohjelmisto on toistensa kanssa vuorovaikutuksessa toimivien komponenttien kokoelma. • Esim. Kokoonpanoteollisuus (autot, mikrot, viihde-elektroniikka): Tehdas ostaa komponentit ja kokoaa tuotteen valmiista komponenteista. Komponentteja hyödyntäviltä kokoajilta vaaditaan komponenttien liittämistaito ja komponentteja valmistavilta vaaditaan yksityiskohtaista tietoutta komponenttien valmistamisesta • Olio-ohjelmointia voisi kutsua tällä perusteella kokoonpano-ohjelmoinniksi!

  10. Mitä on olio-ohjelmointi? • Oliot ja niiden kommunikointi (Objects and communication) • Luokat (Classes) • Kapselointi (Encapsulation) • Periytyminen (Inheritance) • Monimuotoisuus (Polymorfism) • Geneeriset/parametrisoidut tyypit ( generic or parameterized types)

  11. Oliot ja niiden kommunikointi • Olio (object) on tietojen ja palvelujen kokonaisuus. Olio on ohjelman toteutuksen kannalta ajonaikainen keskusmuistista tehty tilanvaraus. • Viesti (message) on oliolle lähetetty pyyntö suorittaa jonkin olion vastuulla oleva palvelu. • Viesti on olioiden kommunikointitapa. Ohjelman toteutuksen kannalta viesti on olion kautta tapahtuva luokan aliohjelman kutsu. • Palvelu (service) on olion asiakasolioilleen tarjoama ja olion vastuulla oleva tehtävä. Toteutuksen kannalta palvelu on luokan aliohjelman esittely • Olio voi olla jokin tietty yritys, tuote, päivämäärä, käyttäjä, kokonaisluku jne. Oliot voivat olla siis eri abstraktiotasolla. Yhteistä olioille on se, että kullakin oliolla on vastuullaan omat tietonsa ja niiden käsittelyyn tarvittavat palvelut.

  12. Tiedon piilotus • Oliolähestysmistavassa eräs keskeinen periaate on tiedon piilotuksen (information hiding) periaate • Tämä tarkoittaa sitä, että vain olio itse voi käsitellä omia tietojansa. Olio ei siis näe toisen olion tietoja eikä kykene niitä käsittelemään. • Tiedon piilotus mahdollistaa olion käytön komponenttina, joka on mahdollista liittää muihin komponentteihin tietämättä sen sisältöä. Ainoastaan komponentin käyttötarkoitus ja ulkoinen rajapinta on tiedettävä, jotta oliota voisi käyttää • Ulkoinen rajapinta sisältää olion palvelut.

  13. Luokat tai tyypit • Luokka (class) on olioiden tyyppi. Joissakin oliokielissä sitä kutsutaankin tyypiksi (type) . Jokainen olio kuuluu luokkaan. Olio on luokkansa ilmentymä. Toteutuksen kannalta luokka on ohjelmoijan määrittelemä tyyppi • Attribuutti (attribute) on luokassa määriteltävä luokan olion ominaisuutta kuvaileva tieto. Toteutuksen kannalta attribuutti on luokassa määriteltävä tieto. C++ vastine tietojäsen (data member) • Palvelu (service) on luokassa esitelty luokan olioiden vastuulla oleva tehtävä. Toteutuksen kannalta palvelu on luokkaan liitetyn aliohjelman esittely. • Metodi (method) on palvelun toteutustapa. Toteutuksen kannalta metodi on luokkaan liittetty aliohjelma. C++ vastine aliohjelmajäsen (function member)

  14. Kapselointi (Encapsulation) • Kapseloinnissa yhdistetään tietotyyppin tietorakenne ja sen toiminnot. Samalla kätketään tietotyypin sisäinen rakenne ja toimintojen toteutus. • Kapseloinnilla pakotetaan ohjelmoija käyttämän olion käsittelyssä vain sen tyyppiin kuuluvia menetelmiä. • Kapseloinnilla pienennetään muutos- ja ylläpitokustannuksia

  15. Esimerkki tietotyypin vs. luokan käyttö • Tietotyypin käyttö: Kokonaisluku muuttuja; muuttujan tilanvaraus muuttuja = 2; tyyppiin liitetyn toimenpiteen käyttö cout<< “Luku on: “ <<luku ; muuttujan sisältöön viittaus • Luokan käyttö Päivämäärä päivä; päivä-olion tilanvaraus päivä = 1.1.1997; luokkaan liitetyn palvelun käyttö päivä.Näytä; luokkaan liitetyn palvelun käyttö

  16. Erilaisia olioita • Kohdeoliot liittyvät kohdealueen liiketoiminnan ilmiöihin, esim. asiakas ja tilaus • Liittymäoliot huolehtivat eri järjestelmien välisestä kommunikoinnista, esim. käyttöliittymäoliosta ikkuna ja painike • Perustieto-oliot, joita käytetään muiden luokkien koostamisessa, esim. päivämäärä • Tekniset oliot voivat olla toteutusvälineen tarjoamia apuvälineitä tai vaikkapa ajonaikaisia muiden olioiden keskusmuistiosoitteista kirjaa pitäviä tietorakenneolioita • Tietovarasto-oliot huolehtivat tietoja sisältävien pysyvien olioiden talletuksesta tietovarastoon • Ohjausoliot liittyvät tiettyyn tehtävään ja liittävät yhteen ko. tehtävässä tarvittavia olioita

  17. Luokka • Luokka (class) on ohjelmoijan määrittelemä tyyppi, jonka avulla kapselointi toteutetaan • Luokka on abstraktin tietotyypin (ADT, Abstractdata type) toteutus • liittää tyyppiin kuuluvat attribuutit (tietojäsen, data member) ja attribuutteja käsittelevät metodit (aliohjelmajäsen, function member) yhteen • Luokkien käyttöön liittyvät aiheet ovat: • luokkatyypin määrittely • luokkatyypin aliohjelmien toteutus • luokkatyypin palveluiden käyttö olioiden avulla • olioiden luonti eli tilanvaraus ja tuhoaminen eli tilanvapautus • viestin välitys oliolle

  18. Esimerkki struct luokasta #include <iostream> using namespace std; struct Luku { int luku; }; int main() { Luku tietue; cout<<"\nSyötä luku: "; cin>>tietue.luku; cout<<"Syöttämäsi luku on: "<<tietue.luku; return 0; } • struct-määreellä määritellyn luokan jäsenet ovat julkisia

  19. Esimerkki class luokasta #include <iostream.h> class Luku { int luku; //yksityinen jäsen public: //public määreen jäljessä on luokan julkiset palvelut void kysy(); void nayta(); }; void Luku::kysy() //luokan aliohjelmajäsen, joka käsittelee //luokan tietojäseniä { cout<<"\nSyötä luku: "; cin>>luku; } void Luku::nayta() //luokan aliohjelmajäsen, joka käsittelee //luokan tietojäseniä { cout<<"\nSyöttämäsi luku on: "<<luku; } int main(void) { Luku Olio; Olio.kysy(); Olio.nayta(); return 0; } • class-määreellä määritellyn luokan jäsenet ovat oletusarvoisesti yksityisiä eli ne näkyvät vain luokan omissa aliohjelmissa Luku- luokka UML luokkakaaviona

  20. Luokka • Luokan julkiset palvelut muodostavat luokan liittymän (interface) luokan asiakkaisiin • Luokkatyypin määrittely tarkoittaa luokan tietojäsenten ja aliohjelmajäsenten esittelyä. Ei varaa muistia olion talletusta varten • Luokan määrittely muotoa: luokan_tyyppi luokan_nimi { tietojäsenten esittely aliohjelmajäsenten esittely }; • luokan_tyyppi class, struct, union • tietojäsenet voivat olla mitä tahansa tyyppiä olevia tietoja tai olioita • aliohjelmajäsenet ovat tietojäseniä käsittelevien aliohjelmien esittelyitä

  21. Luokan jäsenten näkyvyys • Luokan jäsenten näkyvyyteen voidaan vaikuttaa luokkatyyppien struct ja class yhteydessä varatuilla sanoilla private, protected ja public (=saantimääreitä, access specifiers) private=yksityinen public=julkinen protected=suojattu, liittyy periytymiseen, tiedot näkyvät myös aliluokissa

  22. Luokkien nimeämiskäytännöstä • Nimeämisellä huomattava vaikutus luokkien käytettävyyteen • Luokan nimi: aloitetaan suurella kirjaimella • Luokan tietojäsenen nimi: aloitetaan pienellä kirjaimella, jos tietojäsen on tavallinen muuttuja ja suurella kirjaimella, jos tietojäsen edustaa oliota • Luokan aliohjelman nimi: aloitetaan pienellä kirjaimella • Luokan aliohjelman nimen tulisi muistuttaa aliohjelman tarjoamasta palvelusta • Luokan julkiset palvelut muodostavat luokan “julkisivun”, liittymän olisi oltava mahdollisimman edustava ja selkeä • Luokan määrittely toimii samalla luokan esittelynä, mutta joskus on tarpeen esitellä luokka ilman tietojäsenten ja aliohjelmajäsenten esittelyä (kun kaksi luokkaa sisältävät viittauksia ristikkäin toisiinsa) class Auto; class Omistaja { Auto* Auto_olio; char omistajannimi20; ... }; class Auto { Omistaja* Omistaja_olio; char rekisteri8; ... };

  23. Luokan metodit ja viestit • Luokan aliohjelman toteutus eli metodi: tyyppi luokan_nimi::aliohjelman_nimi (parametrit) { aliohjelman runko } • Viestin lähettäminen luokkaan luodulle oliolle on luokan aliohjelman kutsu. Aliohjelma käsittelee sen olion tietojäseniä, jolle viesti on saapunut. Eri kutsukerroilla sama aliohjelma siis käsittelee eri olioiden tietojäseniä. Mistä aliohjelma tietää, minkä olion tietoja se käsittelee, kun aliohjelmassa viitataan tietojäseniin ilman erityistä olion tunnusta? • C++-kielessä this-osoitin sisältää viestin saaneen olion keskusmuistiosoitteen. This-osoitinta voidaan käyttää luokkaan kuuluvissa aliohjelmissa. • this-osoitin on valmiiksi esitelty: Luokan_nimi* const this; //this-osoitin on vakio-osoitin

  24. this-osoitin esimerkki class X { int m; public: int readm() {return this->m;} //ei välttämätöntä, return m myös ok. • Käytetään yleensä aliohjelmissa, joissa käytetään osoittimia suoraan class dlink { dlink* pre; //edellinen dlink* suc; //seuraava public: void append(dlink*); ..... } void dlink::append(dlink* p) { p->suc = suc; p->pre = this; suc->pre =p; suc = p; }

  25. Luokan käyttäminen olioiden kautta • Asiakasolio lähettää palvelupyynnön eli viestin palvelinoliolle, joka sitten suorittaa palveluun liittyvän metodin ja/tai delegoi edelleen palvelupyynnön jollekin toiselle oliolle • Asiakasoliolla on oltava tiedossaan palvelinolion tunnus, jonka se voidaan saada haltuunsa: • Palvelinolion tunnus näkyy oliolle globaalisti tai nimiarvaruutensa perusteella • palvelinolion tunnus on talletettu tietojäsenen sisällöksi • asiakasolio luo uuden palvelinolion • asiakasolion aliohjelma saa palvelinolion tunnuksen parametrina oma asiakasolioltaan (palvelupyynnön delegointi)

  26. Esimerkki delegoinnista • Henkilö-luokan olio delegoin tehtävän parametrina saadulle Osasto-oliolle #include <iostream> using namespace std; class Osasto { ... public: void Nayta(); }; class Henkilo { ... public: void KysyOsastolta(Osasto &); }; void Henkilo::KysysOsastolta(Osasto& Olio_osasto) { .. Olio_osasto.Nayta(); } ... int main() { Henkilo Eka; Osasto Olio_osasto; ... Eka.KysyOsastolta(Olio_osasto);

  27. Viestinvälityksen suunnittelu käyttäen UML sekvenssikaaviota • Esim. herätyskellon sekvenssikaavio

  28. main-ohjelman rooli luokkien käyttäjänä #include <iostream.h> #include “sovellus.hpp” int main() { Sovellus Sovellusolio; //olion tilanvaraus Sovelluolio.aja(); //olion palvelupyyntö return 0; }

  29. Luokan jäsenet class luokan_nimi { tyypit: enum, struct, class, typedef tiedot: static aliohjelmat: static, inline, const, virtual ystävät: friend }; • Luokassa esiteltävät tietojäsenet voivat olla oliokohtaisia tai luokkakohtaisia

  30. Luokan oliokohtaiset tietojäsenet • Olion muistinvarausluokan mukaiset tietojäsenet • Käyttö: olion tilatiedot, pakolliset koostumussuhteet • Elinikä: samanikäisiä kuin olion tunnus #include <iostream> class Merkkijono { char jono25; ... }; int main(void) { Merkkijono Automaattinen; Merkkijono *Dynaaminen=new Merkkijono; ... delete Dynaaminen; return 0; }

  31. Luokan dynaamiset tietojäsenet • Käyttö: olion tilatiedot, ehdolliset tai pakolliset koostumus- ja yhteyssuhteet • Toteutustapa: osoittimet • Elinikä: ohjelmoija päättää tilanvarauksen ja -vapautuksen ajankohdan #include <iostream> class Merkkijono { char* jono; ... }; int main(void) { Merkkijono Automaattinen; Merkkijono *Dynaaminen=new Merkkijono; ... delete Dynaaminen; return 0; } • Kun oliolle vartaan tila, tulee automaattisesti varatuksi osoitinmuuttujan tarvitsema tila, mutta ei merkkijonon vaatimaa muistitilaa. Ohjelmoijan on itse tehtävätilanvaraus ja -vapautus olion dynaamisille tietojäsenille luokan aliohjelmissa. Kun olion tila vapautuu, häviää osoitinmuuttujan jono tilanvaraus automaattisesti, mutta ei jono-osoittimen osoittaman muistialueen tilanvaraus

  32. Luokan luokkakohtaiset tiedot • Käyttö: luokkaa kuvailevat tiedot, kaikki oliot voivat käyttää • Elinikä: staattinen, ei riipu luokan olioiden eliniästä • Toteutustapa: esittely varatulla sanalla static #include <iostream> class Merkkijono { char jono25; static int lkm; ... }; int main(void) { Merkkijono Automaattinen; Merkkijono *Dynaaminen=new Merkkijono; ... delete Dynaaminen; return 0; }

  33. Luokan aliohjelmajäsenet • Oliokohtaisia tietoja käsittelevät aliohjelmat • muodostimet (constructor): olion alustus ja kopiointi olion tilanvarauksen yhteydessä • hajotin (destructor): olion tyhjennys ja tilanvapautus • sijoitusoperaattori=: alustus tilanvarauksen jälkeen • muut ohjelmoijan määrittelemät aliohjelmat inline, const, virtual • Luokkakohtaisia tietoja käsittelevät aliohjelmat: • static, voidaan käyttää lisämääreitä inline ja const class Luokka { tyyppi aliohjelma1() {...} // inline-aliohjelman runko toteutettu suoraan esittelyn yhteyteen inline tyyppi Luokka::aliohjelma2() //runko toteutettu //erikseen { ... } • Vakioaliohjelma ei voi muuttaa olion tietoja tyyppi aliohjelma(parametrit) const;

  34. Vakio-oliot • Vakio-olion parametrina saanut aliohjelma ei voi kutsua vakio-olion kautta muita kuin luokan vakioaliohjelmia #include <iostream> class Henkilo ... public: char* etunimi() const; void vaihdaEtunimi(const char*); }; void aliohjelma(Henkilo& Olio1, const Henkilo& Olio2) { Olio1.vaihdaEtunimi(“Maija”); cout<<Olio2.etunimi(); }

  35. Olion luonti eli tilanvaraus • Olion esittely liittää tunnuksen nimen olion tyyppiin eli luokkaan • Olion määrittely luo olion eli määrittely varaa keskusmuistitilan olion tiedoille

  36. Olioiden muistinvarausluokat: Automaattinen • olio on paikallinen lohkossa • järjestelmä varaa oliolle keskusmuistitilan olion määrittelyn yhteydessä pinosta • järjestelmä vapauttaa oliolle varatun keskusmuistitilan automaattisesti lohkon loppuessa • esittely ja määrittely: Luokan_nimi Olion_tunnus Henkilo Hlo_olio; • Ovat olemassa tietyn palveluketjun tai metodin suorituksen ajan • Käytetään väliaikaisina työolioina, kun käsiteltävien olioiden lukumäärä on tiedossa ohjelman kirjoitusvaiheessa ja kun olion ei tarvitse olla olemassa sen luoneen ohjelmalohkon loputtua

  37. Olioiden muistinvarausluokat: Dynaaminen • ohjelmoija varaa oliolle keskusmuistitilan new-operaattorilla vapaasta muistista eli keosta • ohjelmoija vapauttaa tilan delete-operaattorilla • olioiden tilanvaraus ei häviä automaattisesti, vaan ohjelmoijan on vapautettava tila • Esittely ja määrittely erikseen: Luokan_nimi* Olion_tunnus; //osoitinmuuttujan esittely Olion_tunnus = new Luokan_nimi ///tilanvaraus Henkilo * Hlo_olio; Hlo_olio = new Henkilo; • Esittely ja määrittely yhtäaikaisesti: Luokan_nimi* Olion_tunnus = new Luokan_nimi Henkilo* Hlo_olio=new Henkilo; • Hlo_olio on osoitinmuuttuja, joka sisältää osoitteen oliolle varatun keskusmuistialueen alkuun • tarvitaan osoittimia ja dynaamista muistinhallintaa

  38. Olioiden muistinvarausluokat: Dynaaminen • Olion tilanvapautus: delete Olion_tunnus; void aliohjelma(void) { Henkilo Hlo_olio1; Henkilo* Hlo_olio2 = new Henkilo; static Henkilo Hlo_olio; .... delete Hlo_olio2; } • Oliotaulukon vapautus: delete  Oliot; Henkilo* Oliot = new Henkilo5; ... delete Oliot;

  39. Olioiden muistinvarausluokat:Staattinen • olio voi olla globaali tai static-määreellä esitelty paikallinen olio • järjestelmä varaa oliolle keskusmuistitilan pääohjelman käynnistyksen yhteydessä • järjestelmä vapauttaa oliolle varatun keskusmuistitilan pääohjelman loppuessa • Esittely ja määrittely: static Luokan_nimi Olion_tunnus; static Luokan_nimi* Olion_tunnus = new Luokan_nimi; { static Henkilo Hlo_olio1; static Henkilo* Hlo_olio2; Hlo_olio2=new Henkilo; } • Staattiset oliot ovat olemassa koko sovelluksen käyttöajan • Staattiset oliot sisältävät usein sovellukseen, palveluketjuun tai luokkaan liitttyvää kirjanpito- tms. tietoa, jonka tulee olla käytettävissä aina

  40. Viestin välitys oliolle • Viesti on luokan aliohjelman kutsu • Viestin välitys automaattiselle oliolle: Olion_tunnus.Aliohjelman_nimi(); • Viestin välitys dynaamiselle oliolle: if (Olion_tunnus) Olion_tunnus->aliohjelman_nimi(); Henkilo Olio1; Henkilo* Olio2=new Henkilo; Olio1.kysy(); Olio1.nayta(); if (Olio2) Olio2->kysy(); if (Olio2) Olio2->nayta(); delete Olio2;

  41. Olioiden luonti • Olion luontiin liittyvät vaiheet: • olion tilanvaraus • olion alustus • Olion alustus tapahtuu tilanvarauksen yhteydessä • Alustus muodostin (constructor) -aliohjelmassa • Muodostimia kolmenlaisia: • oletusmuodostin (default constructor) • olion tietojäsenten alustus oletusarvoilla • kopiointimuodostin (copy constructor) • olion tietojäsenten alustus toisesta oliosta kopioimalla • parametrilliset muodostimet • olion tietojäsenten alustus ohjelmoijan tapauskohtaisesti määräämillä alkuarvoilla • Luokkaan määritellään muodostimia, jotta voitaisiin varmistaa, että olion tietojäsenet ovat alustettuja ja että ohjelma ei keskeydy ajonaikaiseen virheeseen tietojäsenen sisältöön viitattaessa • Järjestelmä kutsuu muodostinta automaattisesti olion tilanvarauksen yhteydessä

  42. Oletusmuodostin (default constructor) • Järjestelmä kutsuu oletusmuodostina automaattisesti olion tilanvarauksen yhteydessä Luokka Olio; //automaattinen muodostimen kutsu Luokka Olio = Luokka(); //ohjelmoijan mudostimen kutsu Luokka *Olio=new Luokka; LUOkka *Olio=new Luokka(); • Oletusmuodostimen esittely class Luokka { ... public: Luokka(); //oletusmuodostin }; • Oletusmuodostimen määrittely eli toteutus: Luokka::Luokka(): tietojäsenten alustukset //joko näin { tietojäsenten alustukset //tai näin muodostimen runko } • Tietojäsenten alustus muodostimen 1. rivillä Luokka::Luokka(): tieto(lauseke), tieto(lauseke),... { } tieto:alustettava tietojäsen lauseke: muuttuja, vakio tai jokin muu lauseke, jonka arvolla tietojäsen alustuu • jos alustuslauseke yksinkertainen • jos alustettava tietojäsen esitelty vakioksi const • jos alustettava tietojäsen on viittausmuuttuja

  43. Esimerkki oletusmuodostimesta #include <iostream> Using namespace std; class Pvm { int pp, kk, vv; public: Pvm(); void nayta() const; }; Pvm::Pvm() : pp(1), kk(2), vv(96) { } void Pvm::nayta() const { cout<<pp<<'/'<<kk<<'/'<<vv; } int main(void) { Pvm Paiva; Paiva.nayta(); return 0; }

  44. 2. esimerkki oletusmuodostimesta • Tietojäsenten alustus muodostimen rungossa: Luokka::Luokka() { tieto = lauseke; ... } #include <iostream> #include <time> class Pvm { int pp, kk, vv; public: Pvm(); void nayta() const; }; Pvm::Pvm() { time_t sek; tm *paiva; time(&sek); paiva = localtime(&sek); pp = paiva->tm_mday; kk = paiva->tm_mon + 1; vv = paiva->tm_year; } void Pvm::nayta() const { cout<<pp<<'/'<<kk<<'/'<<vv; } int main(void) { Pvm Paiva; Paiva.nayta(); return 0; }

  45. Parametrillinen muodostin • Jos ohjelmoija haluaa alustaa oliot tilanvarauksen yhteydessä tapauskohtaisilla alkuarvoilla • Parametrillinen muodostin on aina ohjelmoijan kirjoittama • Samat säännöt kuin oletusmuodostimella • Poikkeuksia: • Parametrillisen muodostimen parametreihin voidaan määritellä tarvittaessa myös oletusarvot • Luokka voi sisältää useita erilaisilla parametreilla varustettuja muodostimia • Kääntäjä ei generoi oletusmuodostimia, jos ohjelmoija on määritellyt luokkaan parametrillisen muodostimen

  46. Parametrillinen muodostin esimerkki 1 #include <iostream> #include <time> class Pvm { int pp, kk, vv; public: Pvm(const int, const int, const int); //parametrillinen muodostin void nayta()const; }; Pvm::Pvm(const int p_pp, const int p_kk, const int p_vv) : pp(p_pp), kk(p_kk), vv(p_vv) { } void Pvm::nayta() const { cout<<pp<<'/'<<kk<<'/'<<vv; } int main(void) { Pvm Paiva(3, 3, 96); //Paiva-olion luonti ja alustus Paiva.nayta(); return 0; }

  47. Parametrillinen muodostin esimerkki 2 #include <iostream> class Pvm { int pp, kk, vv; public: Pvm(const int, const int, const int = 96); void nayta() const; }; Pvm::Pvm(const int p_pp, const int p_kk, const int p_vv) { pp = p_pp; kk = p_kk; vv = p_vv; } void Pvm::nayta() const { cout<<pp<<'/'<<kk<<'/'<<vv; } int main(void) { Pvm Paiva1(1, 2); Pvm Paiva2(3, 3, 97); cout<<"Päivä1: "; Paiva1 Paiva2.nayta(); return 0; Paiva2.Nayta(); cout<<"\nPäivä2: "; }

  48. Kopiomuodostin (copy constructor) • alustaa olion tietojäsenet saman luokan olemassa olevan olion tiedoilla • Automaattisen olion tilanvaraus ja kopiointimuodostimen kutsu: Luokka Uusi_olio(Vanha_olio); //Vanha_olio automaattinen Luokka Uusi_olio = Vanha_olio; // “ Luokka Uusi_olio(*Vanha_olio); // Vanha_olio dynaa,omem Luokka Uusi_olio = *Vanha_olio // “ • Dynaamisen olion tilanvaraus ja kopiontimuodostimen kutsu: Luokka* Uusi_olio; Uusi_olio=new Luokka (Vanha_olio);//Vanha_olio automaattinen Uusi_olio=new Luokka (*Vanha_olio); //Vanha_olio dynaaminen Pvm Paiva1(1,2,96); Pvm Paiva2(Paiva1); Pvm* Paiva3=new Pvm(Paiva1); Pvm* Paiva4=new Pbm(*Paiva3); Pvm Paiva5(*Paiva3); Pvm Paiva6=Paiva5; • Ohjelmoija voi määritellä itse kopiointimuodostimen • Kopiointimuodostimen esittelytavat: Luokka (const Luokka &); Luokka (const Luokka &, parametri = alkuarvo, …);

  49. #include <iostream> #include <time> class Pvm { int pp, kk, vv; public: Pvm(const int, const int); Pvm(const Pvm &, const int = 96);//kopiomuodostimen esittely void nayta() const; }; Pvm::Pvm(const int p_pp, const int p_kk) : pp(p_pp), kk(p_kk) { time_t sek; tm *paiva; time(&sek); paiva = localtime(&sek); vv = paiva->tm_year; } } Pvm::Pvm(const Pvm &p_pvm, const int p_vv) : pp(p_pvm.pp), kk(p_pvm.kk) { vv = p_vv; } void Pvm::nayta() const { cout<<pp<<'/'<<kk<<'/'<<vv; } int main(void) { Pvm Paiva1(1, 2); Pvm Paiva2(Paiva1);//olion luonti kopiomuodostinta käyttäen Pvm Paiva3(Paiva1, 97); cout<<"Päivä1: "; Paiva1.nayta(); cout<<"\nPäivä2: "; Paiva2.nayta(); cout<<"\nPäivä3: "; Paiva3.nayta(); return 0; } Kopiomuodostin (copy constructor)

  50. Sijoitus olioon sijoitusoperaattorilla • Sijoitus toimi samalla tavalla kuin kopiointimuodostin: sijoitettavan olion tietojäsenten sisällöt kopioituvat vastaanottavan olion tietojäsenten sisällöksi Paiva1 = Paiva2; Paiva1 = *Paiva2; *Paiva1 = Paiva2; *Paiva1 = *Paiva2; Paiva3 = *Paiva2 = Paiva1; • Sijoitettavien olioiden on oltava samaa tyyppiä • Kääntäjä generoi sijoitusta varten sijoitusaliohjelman • Ohjelmoija voi kirjoittaa sijoitusaliohjelman itse (= operaattorin ylikuormitus)

More Related