Ohjelman virheet ja poikkeusten käsittely

Koko: px
Aloita esitys sivulta:

Download "Ohjelman virheet ja poikkeusten käsittely"

Transkriptio

1 Ohjelman virheet ja poikkeusten käsittely 17 Ohjelman virheet ja poikkeusten käsittely Poikkeukset ovat tapa ilmoittaa virheistä ja odottamattomista tilanteista C++-ohjelmassasi. Poikkeusten käyttö virheiden ilmoittamisessa ei ole pakollista ja joskus onkin mukavampaa käsitellä ne jollain toisella tavalla. On kuitenkin tärkeää ymmärtää, miten poikkeukset toimivat, koska niitä voi muodostua kielen standardiominaisuuksien käytössä, kuten operaattoreiden new ja dynamic_cast käytössä. Poikkeuksia käytetään runsaasti myös standardikirjastossa. Tämän luvun aiheita ovat: Mikä on poikkeus Miten poikkeuksia käytetään ilmoittamaan ohjelman virhetilanteista Miten poikkeukset käsitellään Mitkä poikkeukset on määritelty standardikirjastossa Miten voidaan rajoittaa minkä tyyppisiä poikkeuksia funktio voi muodostaa Miten käsitellään poikkeukset, jotka on muodostettu muodostinfunktiossa Miten muodostettu poikkeus voi vaikuttaa luokan tuhoajafunktioon Virheiden käsittely Virheiden käsittely on olennainen osa onnistunutta ohjelmointia. Ohjelman tulee pystyä käsittelemään mahdolliset virheet ja epänormaalit tapahtumat. Tämä saattaa vaatia enemmän työtä kuin sen koodin kirjoittaminen, joka suoritetaan asioiden mennessä niin kuin niiden pitäisikin. Virheen käsittelevän koodin laatu ratkaisee, kuinka vakaa ohjelmasi on ja näyttelee usein pääosaa ohjelman käyttäjäystävälliseksi tekemisessä. Sillä on myös suuri vaikutus siihen, miten helppoa on virheiden korjaus. Kaikki virheet eivät ole samanarvoisia ja virheen luonne määrää sen, miten se on parasta käsitellä ohjelmassasi. Usein virheet kannattaa käsitellä heti siellä missä ne tapahtuvatkin. Ajatellaan esimerkiksi syötteen lukua näppäimistöltä: väärän merkin kirjoittaminen saa aikaan virheellisen 669

2 C++ Ohjelmoijan käsikirja syötteen, mutta se ei ole varsinaisesti vakava ongelma. Virheellinen syöte on yleensä varsin helppo havaita ja kaikkein paras tapa on yleensä hylätä syöte ja pyytää käyttäjää syöttämään se uudelleen. Tässä tapauksessa virheen käsittelevä koodi on rakennettu syötteen lukevaan koodiin. Vakavammistakin virhetilanteista on mahdollista toipua siten, että se ei haittaa ohjelman muuta toimintaa. Kun virhe havaitaan funktiossa, on usein paras palauttaa jonkinlainen virhekoodi kutsujalle, jolloin kutsuja voi päättää, miten virhetilanne on paras käsitellä. Poikkeukset mahdollistavat uuden tavan käsitellä virheitä - ne eivät korvaa edellä kuvattuja käsittelytapoja. Poikkeusten suurin hyöty on siinä, että niiden avulla virheen käsittelevä koodi on aivan erillään itse virheen aiheuttaneesta koodista. Mitä poikkeukset ovat? Poikkeus on tilapäinen, minkä tahansa tyyppinen olio, jota käytetään virheen ilmoittamiseen. Poikkeus voi olla perustietotyypin olio, kuten int tai char*, mutta yleensä se on erityisesti tähän tarkoitukseen määritellyn luokan olio. Poikkeusolion tarkoitus on välittää tietoa poikkeuksen käsittelevälle koodille kohdasta, jossa poikkeus tapahtui. Tämä tapahtuu parhaiten luokan oliona. Kun ohjelmassasi tapahtuu virhe, voit kertoa virheestä muodostamalla poikkeuksen. Koodi, joka muodostaa poikkeuksen, täytyy kirjoittaa aaltosulkeilla ympäröityyn lohkoon, -lohkoon. Jos lause, joka ei ole -lohkossa, muodostaa poikkeuksen, ohjelman suoritus päättyy. Palaamme tähän hetken kuluttua. -lohkon perässä on yksi tai useampia catch-lohkoja. Kukin catch-lohko sisältää koodin, joka käsittelee tietyn tyyppisen poikkeuksen; tästä syystä catch-lohkoa kutsutaan usein virheen käsittelijäksi. Eli jos muodostat poikkeuksia virheen tapahtuessa, koodi, joka käsittelee virhetilanteen, on catch-lohkoissa, täydellisesti erotettuna koodista, joka suoritetaan, kun kaikki menee oikein. Koodi, joka käsittelee normaalit tapahtumat, on täydellisesti erotettu koodista, joka käsittelee epänormaalit tapahtumat. Koodi, joka saattaa muodostaa poikkeuksia, tulee kirjoittaa - lohkoon. Kun poikkeus on muodostettu, catch-lohkot tutkitaan järjestyksessä. Ohjelman suoritus siirtyy ensimmäiseen catch- lohkoon, jonka parametri vastaa muodostetun poikkeuksen tyyppiä. Tarvittaessa tehdään automaattinen muunnos. // Koodi, joka saattaa muodostaa poikkeuksia catch(1. poikkeustyypin määrittelevä parametri) // Koodi, joka käsittelee poikkeuksen catch(2. poikkeustyypin määrittelevä parametri) // Koodi, joka käsittelee poikkeuksen catch(n. poikkeustyypin määrittelevä parametri) // Koodi, joka käsittelee poikkeuksen 670

3 Ohjelman virheet ja poikkeusten käsittely Kuten kaavio havainnollistaa, -lohko on tavallinen aaltosulkeiden välissä oleva lohko, jonka edessä on -avainsana. Joka kerta kun -lohko suoritetaan, se voi muodostaa erilaisia poikkeuksia. Täten sen perässä voi olla erilaisia catch-lohkoja, joista jokainen käsittelee erilaisen poikkeuksen. Poikkeuksen tyyppi kirjoitetaan catch-avainsanan perässä oleviin sulkeisiin. catchavainsana puolestaan sijoitetaan catch-lohkon aaltosulkeiden eteen. Tietty catch-lohko suoritetaan vain, jos sen tyyppiä vastaava poikkeus on muodostettu. Jos lohko ei muodosta poikkeusta, mitään catch-lohkoa ei suoriteta. Et voi hypätä -lohkoon esimerkiksi goto-käskyllä. Ainut tapa suorittaa -lohko on aloittaa sen alusta, lohkon avaavan aaltosulkeen jälkeen tulevasta ensimmäisestä lauseesta. Poikkeuksen muodostaminen Nyt on korkea aika jo muodostaa poikkeuksia, joten katsotaan, mitä tapahtuu, kun niin teemme! Vaikka sinun tulisikin aina käyttää luokkaolioita poikkeuksissa (kuten teemme myöhemmin tässä luvussa), aloitamme perustietotyypeillä, koska näin koodi pysyy hyvin yksinkertaisena. Poikkeus muodostetaan throw-lauseella, joka kirjoitetaan throw-avainsanan avulla. Seuraavassa on esimerkki poikkeuksen muodostamisesta: // Koodi, joka voi muodostaa poikkeuksen if(testi > 5) throw "testi on suurempi kuin 5"; // Muodostetaan poikkeus // Tämä koodi suoritetaan, jos poikkeusta ei muodosteta catch(const char* viesti) // Koodi, joka käsittelee poikkeuksen // Tämä koodi suoritetaan, jos poikkeuksen tyyppi on char* // tai 'const char*' cout << viesti << endl; Jos muuttujan testi arvo on suurempi kuin 5, throw-lause muodostaa poikkeuksen. Tällöin poikkeus on testi on suurempi kuin 5. Ohjelman suoritus siirtyy välittömästi ulos lohkosta ensimmäiseen poikkeuksen käsittelijään, jonka tyyppi vastaa muodostetun poikkeuksen tyyppiä: const char*. Tässä meillä on vain yksi käsittelijä, joka sattuu sopivasti käsittelemään const char* -tyyppiset poikkeukset, joten catch-lohkon koodi suoritetaan ja poikkeus tulostetaan.! Kääntäjä ei itse asiassa huomioi const-avainsanaa vertaillessaan poikkeuksen tyyppiä catch-parametrin tyyppiin. Käsittelemme tätä tarkemmin myöhemmin. 671

4 C++ Ohjelmoijan käsikirja Kokeile itse - Poikkeusten muodostaminen ja käsittely Kokeillaan poikkeuksia esimerkin avulla, jossa muodostamme int- ja const char* -tyyppisiä poikkeuksia. Lisäämme koodiin muutamia tulostuslauseita, jotka helpottavat suorituksen seuraamista: // Esimerkki 17.1 Poikkeusten muodostaminen ja käsittely #include <iostream> using namespace std; int main() cout << endl; for(int i = 0 ; i < 7 ; i++) if(i < 3) throw i; cout << " i, ei muodostettu - arvo on " << i << endl; if(i > 5) throw "Tässä on toinen!"; cout << " Try-lohkon loppu." << endl; catch(const int i) cout << " poikkeus i - arvo on " << i << endl; catch(const char* pviesti) cout << " \"" << pviesti << "\"-poikkeus" << endl; cout << "Silmukan loppu (catch-lohkojen perässä) - i on " << i << endl; 672 return 0; Esimerkin tulostus näyttää seuraavalta: poikkeus i - arvo on 0 Silmukan loppu (catch-lohkojen perässä) - i on 0 poikkeus i - arvo on 1 Silmukan loppu (catch-lohkojen perässä) - i on 1 poikkeus i - arvo on 2 Silmukan loppu (catch-lohkojen perässä) - i on 2 i, ei muodostettu - arvo on 3 Try-lohkon loppu. Silmukan loppu (catch-lohkojen perässä) - i on 3 i, ei muodostettu - arvo on 4 Try-lohkon loppu. Silmukan loppu (catch-lohkojen perässä) - i on 4 i, ei muodostettu - arvo on 5 Try-lohkon loppu. Silmukan loppu (catch-lohkojen perässä) - i on 5

5 Ohjelman virheet ja poikkeusten käsittely i, ei muodostettu - arvo on 6 "Tässä on toinen!"-poikkeus Silmukan loppu (catch-lohkojen perässä) - i on 6 Kuinka se toimii for-silmukassa on -lohko, jossa muodostetaan int-tyyppinen poikkeus, jos i (silmukan laskuri) on pienempi kuin 3, ja const char* -tyyppinen poikkeus, jos i on suurempi kuin 5: if(i < 3) throw i; cout << " i, ei muodostettu - arvo on " << i << endl; if(i > 5) throw "Tässä on toinen!"; cout << " Try-lohkon loppu." << endl; Poikkeuksen muodostaminen siirtää ohjelman suorituksen välittömästi ulos -lohkosta, joten lohkon lopussa oleva tulostuslause suoritetaan vain, jos mitään poikkeusta ei ole muodostettu. Tulostuksesta huomaat, että näin todella tapahtuu. Tulostuslause suoritetaan vain, jos i:n arvo on 3, 4 tai 5. Kaikilla muilla i:n arvoilla muodostetaan poikkeus, eikä tulostuslausetta suoriteta. Ensimmäinen catch-lohko on heti -lohkon perässä: catch(const int i) cout << " poikkeus i - arvo on " << i << endl; -lohkon käsittelijöiden täytyy olla välittömästi -lohkon perässä. Jos sijoitat muuta koodia -lohkon ja ensimmäisen catch-lohkon väliin, tai catch-lohkojen väliin, ohjelma ei käänny. Tämä catch-lohko käsittelee int-tyyppiset poikkeukset ja tulostuksesta huomaat, että se suoritetaan, kun ensimmäinen throw-lause suoritetaan. Tulostuksesta näet myös, että seuraavaa catch-lohkoa ei suoriteta tässä tapauksessa. Kun tämä käsittelijä on suoritettu, ohjelman suoritus siirtyy silmukan viimeiseen lauseeseen. Seuraava käsittelijä käsittelee char*-tyyppiset poikkeukset: catch(const char* pviesti) cout << " \"" << pviesti << "\"-poikkeus" << endl; Kun muodostamme poikkeuksen Tässä on toinen!, ohjelman suoritus siirtyy throw-lauseesta suoraan tähän käsittelijään - ensimmäinen käsittelijä jätetään väliin. Jos poikkeusta ei muodosteta, kumpaakaan catch-lohkoa ei suoriteta. Voit kirjoittaa tämän käsittelijän myös ensimmäiseksi ja ohjelma toimii aivan samaan tapaan. Tässä tapauksessa käsittelijöiden järjestyksellä ei ole merkitystä, mutta näin ei aina ole. Näet myöhemmin tässä luvussa tilanteita, joissa käsittelijöiden järjestyksellä on merkitystä. 673

6 C++ Ohjelmoijan käsikirja Seuraava lause kertoo silmukan kierroksen päättymisestä: cout << "Silmukan loppu (catch-lohkojen perässä) - i on " << i << endl; Tämä koodi suoritetaan riippumatta siitä, onko poikkeuksen käsittelijä suoritettu vai ei. Kuten huomaat, poikkeuksen muodostaminen ei lopeta ohjelman suoritusta - ellet tietysti halua niin tapahtuvan. Jos pystyt korjaamaan poikkeuksen aiheuttaneen ongelman, ohjelman suoritus voi jatkua. Poikkeusten käsittely Nyt, kun olet nähnyt esimerkin, sinulla on jo varsin hyvä kuva tapahtumien järjestyksestä, kun poikkeus muodostetaan. Muitakin asioita tapahtuu kuitenkin taustalla ja oletkin jo saattanut arvata niistä joitakin, jos olet miettinyt, miten ohjelman suoritus siirtyy -lohkosta catchlohkoon. throw/catch-lauseiden suoritusjärjestystä havainnollistetaan alla olevassa kaaviossa: throw poikkeus; catch(tyyppi1 ex) catch(tyyppin ex) catch(tyyppiviimeinen ex) 1.throw-lauseketta käytetään alustamaan väliaikainen olio temp seuraavasti: PoikkeusTyyppi temp(poikkeus); 4. Poikkeuksen kopiota käytetään alustamaan parametri seuraavasti: tyyppin ex(temp); ja suoritus siirtyy käsittelijään. 3.Valitaan ensimmäinen käsittelijä, jonka parametrin tyyppi vastaa poikkeusta. 5.Jos käsittelijän koodi ei toisin määrää, suoritus jatkuu -lohkon catch-lohkojen jälkeen tulevasta ensimmäisestä lauseesta. 2.Kaikkien -lohkossa määriteltyjen automaattisten olioiden tuhoajafunktioita kutsutaan. -lohko on lauselohko, ja tiedätkin jo, että lauselohko määrittelee aina näkyvyysalueen. Poikkeuksen muodostaminen saa aikaan suorituksen välittömän poistumisen -lohkosta, jolloin -lohkossa jo esitellyt automaattiset oliot tuhotaan. Yksikään niistä ei ole enää olemassa, kun käsittelijää suoritetaan. Tämä on erittäin tärkeää - tämähän tarkoittaa sitä, että et saa muodostaa poikkeusoliota, joka on osoitin olioon, joka on paikallinen -lohkossa. Tämä on myös syy siihen, miksi poikkeusolio kopioidaan. 674 Poikkeusolio tulee olla tyyppiä, joka voidaan kopioida. Sellaisen luokan oliota, jonka kopiomuodostin on yksityinen, ei voida käyttää poikkeuksena.

7 Ohjelman virheet ja poikkeusten käsittely Koska throw-lauseketta käytetään väliaikaisen olion alustamiseen - eli luo kopion poikkeuksesta - voit muodostaa poikkeusolioita, jotka ovat paikallisia -lohkossa. Muodostetun poikkeusolion kopiota käytetään sitten alustamaan catch-lohkon parametri, kun käsittelijä on valittu. catch-lohko on myös lauselohko, joten kaikki sen paikalliset automaattiset oliot (parametrit mukaan lukien) tuhotaan, kun catch-lohkon suoritus päättyy. Ellei goto- tai return-lausetta käytetä catch-lohkosta poistumiseen, ohjelman suoritus jatkuu kyseisen -lohkon perässä olevaa viimeistä catch-lohkoa seuraavasta lauseesta. Kun poikkeuksen käsittelijä on valittu ja ohjelman suoritus on siirtynyt käsittelijään, muodostettu poikkeus pidetään käsiteltynä. Näin myös silloin, jos jätät catch-lohkon tyhjäksi eikä se tee mitään. Käsittelemättömät poikkeukset Jos -lohkossa muodostettua poikkeusta ei käsitellä missään catch-lohkoissa, kutsutaan (ellei olla sisäkkäisissä -lohkoissa, joita käsittelemme hetken kuluttua) standardikirjaston terminate()-funktiota. Tämä funktio kutsuu ennalta määriteltyä oletusarvoista suorituksen päättymisfunktiota, joka puolestaan kutsuu standardikirjaston funktiota abort(). Käsittelemätön poikkeus saa aikaan funktion terminate()kutsun. set_terminate(pomapäättymisfunktio); joka kutsuu korvaa Oletusarvoinen suorituksen päättymisfunktio joka kutsuu abort() Funktio abort() päättää koko ohjelman suorituksen välittömästi. Toisin kuin exit(), se ei kutsu yhdenkään staattisen olion tuhoajafunktiota. Oletusarvoisen suorituksen päättymisfunktion oletustoiminta voi olla tuhoisaa joissakin tapauksissa - se saattaa esimerkiksi jättää tiedostot epätasapainoiseen tilaan tai puhelinlinja saattaa jäädä auki. Tällaisissa tilanteissa haluat varmastikin, että asiat lopetetaan oikein. Tämän voit tehdä korvaamalla oletusarvoisen suorituksen päättymisfunktion omalla versiollasi. Korvataksesi oletusarvoisen suorituksen päättymisfunktion, kutsut standardikirjaston funktiota set_terminate(), jonka parametri on terminate_handler-tyyppinen ja palauttaa saman tyyppisen paluuarvon. Tämä tyyppi on määritelty standardiotsikkotiedostossa exception seuraavasti: typedef void (*terminate_handler)(); 675

8 C++ Ohjelmoijan käsikirja terminate_handler on osoitin funktioon, jolla ei ole lainkaan parametrejä eikä palauta mitään paluuarvoa, eli korvaavan funktion tulee olla tämän tyyppinen. Voit tehdä mitä haluat omassa versiossasi suorituksen päättymisfunktiosta, mutta se ei saa palata takaisin ohjelmaan - sen tulee lopulta lopettaa ohjelman suoritus. Oma määrittely funktiostasi saattaisi näyttää vaikka seuraavalta: void omapaattymisfunktio() // Tee tarvittavat toimet, jotta kaikki asiat on lopetettu oikein exit(1); Standardikirjaston exit()-funktion kutsuminen on parempi tapa lopettaa ohjelman suoritus kuin abort()-funktion kutsuminen. exit()-funktion kutsuminen varmistaa, että globaalien olioiden tuhoajafunktiota kutsutaan ja kaikki avoinna olevat syöttö/tulostusvirrat tyhjennetään sekä suljetaan tarvittaessa. Kaikki standardikirjaston väliaikaiset tiedostot poistetaan. exit()-funktiolle välittämäsi kokonaislukuparametri palautetaan käyttöjärjestelmälle tilakoodina. Nollasta poikkeava arvo tarkoittaa ohjelman epänormaalia päättymistä. Yllä olevan funktion asetat suorituksen päättymisfunktioksi seuraavalla lauseella: terminate_handler pvanhafunktio = set_terminate(omapaattymisfunktio); Paluuarvo on osoitin edelliseen päättymisfunktioon, joten voit tarvittaessa palauttaa sen myöhemmin. Kun kutsut set_terminate()-funktiota ensimmäisen kerran, paluuarvo on osoitin oletusarvoiseen suorituksen päättymisfunktioon. Jokainen tämän funktion kutsu palauttaa voimassa olleen päättymisfunktion osoittimen. Tämä tarkoittaa sitä, että voit pitää tietyssä ohjelman osassa voimassa omaa päättymisfunktiotasi ja osassa ohjelmaa oletusarvoista päättymisfunktiota. Voit luonnollisestikin asettaa eri päättymisfunktion ohjelman eri osissa, jotta ohjelman suoritus voidaan päättää asianmukaisesti. Jos ohjelmasi käsittelee esimerkiksi tietokantaa, sinun tulee varmistaa, että tietokanta sammutetaan oikein, kun vakava virhe tapahtuu. Tätä varten voit kirjoittaa oman päättymisfunktion. Ohjelman toinen osa voi käyttää modeemia tiedonsiirtoon, jolloin mitä todennäköisimmin haluat sulkea tiedonsiirtolinjan. Eri tilanteisiin sopivaa päättymisfunktiota voidaan käyttää aina tarvittaessa. 676 Poikkeuksen muodostava koodi Kuten tämän luvun alkupuolella mainittiin, -lohko sisältää koodin, joka voi aiheuttaa poikkeuksen muodostumisen. Tämä ei kuitenkaan tarkoita sitä, että poikkeuksen muodostavan koodin tulisi fyysisesti olla -lohkon aaltosulkeiden sisällä. Sen tulee olla loogisesti -lohkon sisällä. Tämä tarkoittaa sitä, että jos funktiota kutsutaan -lohkosta, funktion mahdollisesti muodostama poikkeus saadaan kiinni -lohkon catch-lohkoissa. Seuraava kaavio havainnollistaa tätä tilannetta.

9 Ohjelman virheet ja poikkeusten käsittely fun1(); Täällä muodostettu poikkeus normaali paluu void fun1() fun3(); void fun3() fun2(); catch(exceptiontyyppi ex) voidaan käsitellä täällä voidaan käsitellä täällä normaali paluu voidaan käsitellä täällä void fun2() normaali paluu Täällä muodostettu poikkeus Täällä muodostettu poikkeus -lohkossa on kaksi funktion kutsua, fun1() ja fun2(). Funktioissa mahdollisesti muodostuvat exceptiontyyppi-tyyppiset poikkeukset saadaan kiinni -lohkon perässä olevassa catchlohkossa. Funktiossa muodostettu poikkeus, jota ei käsitellä funktiossa, voidaan välittää kutsuvalle funktiolle. Jos sitä ei käsitellä sielläkään, se voidaan edelleen välittää ylemmälle kutsutasolle - tätä havainnollistetaan kaaviossa fun3()-funktiossa muodostetulla poikkeuksella. Jos poikkeus saavuttaa kutsutason, jossa ei enää ole catch-käsittelijöitä eikä poikkeusta ole vieläkään käsitelty, kutsutaan suorituksen päättymisfunktiota ohjelman päättämiseksi. Jos samaa funktiota kutsutaan ohjelman eri osista, funktion koodin muodostama poikkeus voidaan käsitellä eri catch-lohkoissa suorituksen eri aikana. Seuraava esimerkki havainnollistaa tällaista tilannetta. fun1(); catch(exceptiontyyppi ex) fun1(); catch(exceptiontyyppi ex) Kun tätä kutsua suoritetaan, funktion fun1() koodi on loogisesti ylemmässä - lohkossa. Kun tätä kutsua suoritetaan, funktion fun1() koodi on loogisesti alemmassa - lohkossa. void fun1() 677

10 C++ Ohjelmoijan käsikirja Kun funktio on suorituksessa ensimmäisen -lohkon kutsun seurauksena, kaikki fun1()- funktion muodostamat exceptiontyyppi-tyyppiset poikkeukset voidaan käsitellä tämän lohkon catch-lohkossa. Kun sitä kutsutaan toisesta -lohkosta, tämän -lohkon catch-lohko käsittelee muodostetut exceptiontyyppi-tyyppiset poikkeukset. Tästä huomaat varmastikin, että voit valita kuhunkin tilanteeseen sopivan suorituksen päättymisfunktion. Jos haluat, voit käsitellä kaikki ohjelmassa tapahtuvat poikkeukset kirjoittamalla main()-funktion koodin -lohkoon ja lisäämällä ohjelmaan tarpeellisen määrän catchlohkoja. Sisäkkäiset -lohkot Voit kirjoittaa -lohkon toisen -lohkon sisälle. Niillä jokaisella on omat catch-lohkonsa, jotka käsittelevät siinä muodostuvat poikkeukset. -lohkon catch-lohkot voivat käsitellä vain kyseisen -lohkon poikkeuksia. Tätä havainnollistetaan seuraavassa kaaviossa: // ulompi -lohko // sisempi -lohko catch(exceptiontyyppi ex) catch(exceptiontyyppi ex) Tämä käsittelijä voi käsitellä sisemmässä -lohkossa muodostettuja poikkeuksia. Tämä käsittelijä voi käsitellä kaikkialla ulommassa -lohkossa muodostettuja poikkeuksia, sekä sisemmässä lohkossa käsittelemättömiä poikkeuksia. 678 Kaaviossa on yksi käsittelijä kumpaakin -lohkoa kohti, mutta niitä voi olla useitakin. Kun sisemmän -lohkon koodi muodostaa poikkeuksen, sen käsittelijät saavat ensin mahdollisuuden käsitellä sen. Jokainen käsittelijä tarkistetaan, vastaako sen tyyppi poikkeuksen tyyppiä. Jos yksikään tyyppi ei vastaa poikkeuksen tyyppiä, ulomman -lohkon käsittelijät saavat mahdollisuuden käsitellä poikkeuksen. Voit sijoittaa -lohkoja tällä tavalla sisäkkäin niin monta kuin ohjelmasi vaatii. Kun poikkeus muodostetaan ulomman -lohkon koodissa, tämän -lohkon catch-käsittelijät käsittelevät sen, vaikka poikkeuksen muodostava lause olisi ennen sisempää -lohkoa. Sisemmän -lohkon käsittelijät eivät milloinkaan voi käsitellä ulomman -lohkon koodissa muodostettua poikkeusta. Luonnollisestikin kummankin -lohkon koodi voi kutsua funktioita. Kun funktio on tällöin suorituksessa, sen koodi on loogisesti siinä -lohkossa, josta sitä kutsuttiin. Osa tai kaikki funktion koodista voi myöskin olla omassa -lohkossaan, joka on funktiota kutsuvan lohkon sisällä.

11 Ohjelman virheet ja poikkeusten käsittely Kokeile itse - Sisäkkäiset -lohkot Tämä kuulostaa sanallisessa muodossa varsin monimutkaiselta, mutta käytännössä se on paljon helpompaa. Voimme rakentaa yksinkertaisen esimerkin, jossa muodostamme poikkeuksen ja katsomme, missä se käsitellään. Jälleen kerran muistutamme, että esimerkki on vain havainnollistamista varten, eli muodostamme int- ja long-tyyppisiä poikkeuksia. Ohjelman koodi, joka havainnollistaa sekä sisäkkäisiä -lohkoja että poikkeusten muodostamista, on seuraava: // Esimerkki 17.2 Poikkeusten muodostaminen sisäkkäisissä -lohkoissa #include <iostream> using namespace std; void muodostase(int i) throw i; int main() for(int i = 0 ; i <= 5 ; i++) cout << endl << "ulompi : "; if(i == 0) throw i; // Muodostaa poikkeuksen // Muodostaa int-poikkeuksen if(i == 1) muodostase(i); cout << endl << " sisempi : "; if(i == 2) throw static_cast<long>(i); // Kutsuu funktiota, joka muodostaa // poikkeuksen // Sisempi -lohko // Muodostaa long-poikkeuksen if(i == 3) muodostase(i); // Kutsuu funktiota, joka muodostaa poikkeuksen // Sisemmän -lohkon loppu catch(int n) cout << endl << "Käsitellään sisemmän -lohkon int. " << "Poikkeus " << n; cout << endl << " ulompi : "; if(i == 4) throw i; // Muodosta int-poikkeus muodostase(i); // Kutsuu funktiota, joka muodostaa poikkeuksen catch(int n) cout << endl << "Käsitellään ulomman -lohkon int. " << "Poikkeus " << n; 679

12 C++ Ohjelmoijan käsikirja catch(long n) cout << endl << "Käsitellään ulomman -lohkon long. " << "Poikkeus " << n; cout << endl; return 0; Ohjelman tulostus on: ulompi : Käsitellään ulomman -lohkon int. Poikkeus 0 ulompi : Käsitellän ulomman -lohkon int. Poikkeus 1 ulompi : sisempi : Käsitellään ulomman -lohkon long. Poikkeus 2 ulompi : sisempi : Käsitellään sisemmän -lohkon int. Poikkeus 3 ulompi : Käsitellään ulomman -lohkon int. Poikkeus 3 ulompi : sisempi : ulompi : Käsitellään ulomman -lohkon int. Poikkeus 4 ulompi : sisempi : ulompi : Käsitellään ulomman -lohkon int. Poikkeus 5 Kuinka se toimii Funktio muodostase() muodostaa parametrinsä mukaisen poikkeuksen. Jos kutsut tätä funktiota -lohkon ulkopuolelta, ohjelman suoritus päättyy välittömästi, koska poikkeusta ei käsitellä ja oletusarvoista suorituksen päättymisfunktiota kutsutaan. Kaikki poikkeukset muodostetaan for-silmukassa. Silmukassa määräämme ensin milloin ja minkä tyyppisen poikkeuksen muodostamme. Tämä tehdään tutkimalla silmukkamuuttujan i arvoa peräkkäisillä if-lauseilla. Vähintään yksi poikkeus muodostetaan silmukan jokaisella kierroksella. Saapuminen kuhunkin -lohkoon tulostetaan, ja koska jokaisella poikkeuksella on oma arvonsa, näemme selvästi, missä kukin poikkeus muodostetaan ja käsitellään. Ensimmäinen poikkeus muodostetaan ulommasta -lohkosta, kun silmukkamuuttujan i arvo on 0: if(i == 0) throw i; // Muodostaa int-poikkeuksen 680 Huomaat tulostuksesta, että ulomman -lohkon perässä oleva catch-lohko, joka käsittelee inttyyppisiä poikkeuksia, käsittelee tämän poikkeuksen. Sisemmän -lohkon catch-lohkolla ei ole tässä mitään merkitystä, koska se voi käsitellä vain sisemmästä -lohkosta muodostettuja poikkeuksia.

13 Ohjelman virheet ja poikkeusten käsittely Seuraava poikkeus muodostetaan ulommassa -lohkossa kutsumalla funktiota muodostase(): if(i == 1) muodostase(i); // Kutsuu funktiota, joka muodostaa poikkeuksen Tämä käsitellään myöskin ulomman -lohkon catch-lohkossa, joka käsittelee int-tyyppiset poikkeukset. Seuraavat kaksi poikkeusta muodostetaan kuitenkin sisemmässä -lohkossa: if(i == 2) throw static_cast<long>(i); // Muodostaa long-poikkeuksen if(i == 3) muodostase(i); // Kutsuu funktiota, joka muodostaa poikkeuksen Ensimmäinen näistä on long-tyyppinen poikkeus. Sisemmälle -lohkolle ei ole catch-lohkoa tämän tyyppiselle poikkeukselle, joten se siirtyy ulompaan -lohkoon, jossa long-tyyppinen catch-lohko käsittelee sen, kuten tulostuksesta huomaat. Toinen poikkeus on int-tyyppinen ja muodostetaan muodostase()-funktion rungossa. Tässä funktiossa ei ole -lohkoa, joten poikkeus siirtyy kohtaan, jossa sitä kutsuttiin sisemmästä -lohkosta. Se käsitellään sitten sisemmän lohkon catch-lohkossa, joka käsittelee int-tyyppiset poikkeukset. Kun jokin sisemmän -lohkon käsittelijä käsittelee poikkeuksen, suoritus jatkuu lopuista ulomman -lohkon lauseista. Eli kun i on 3, saamme tulostuksen sisemmän -lohkon catchlohkosta sekä tulostuksen ulomman -lohkon käsittelijästä, joka käsittelee int-tyyppiset poikkeukset. Jälkimmäinen poikkeus muodostuu sisemmän -lohkon lopussa olevasta funktion muodostase() kutsusta. Lopuksi muodostamme kaksi uutta poikkeusta ulommassa -lohkossa: if(i == 4) throw i; // Muodosta int-poikkeus muodostase(i); // Kutsuu funktiota, joka muodostaa poikkeuksen Ulomman -lohkon int-tyyppiset poikkeukset käsittelevä käsittelijä käsittelee nämä molemmat poikkeukset. Toinen näistä poikkeuksista muodostetaan funktion muodostase() rungossa, ja koska sitä kutsutaan ulommasta -lohkosta, ulomman -lohkon catch-lohko käsittelee sen. Vaikka yksikään näistä poikkeuksista ei ollut kovinkaan realistinen - oikeiden ohjelmien poikkeukset ovat aina luokkaolioita - ne havainnollistivat hyvin poikkeusten muodostamista ja käsittelyä sekä sitä, mitä tapahtuu sisäkkäisissä -lohkoissa. Siirrytään nyt tarkastelemaan lähemmin poikkeuksia, jotka ovat olioita. Luokkaoliot poikkeuksina Voit muodostaa poikkeuksen, joka on millainen tahansa luokkaolio. Pidä kuitenkin mielessä, että poikkeusolion ideana on tuoda käsittelijälle tietoa, missä meni väärin. Tästä syystä on usein järkevää määritellä erityinen poikkeusluokka, joka kuvaa tietyntyyppistä ongelmaa. Tämä on varsin sovelluskohtaista, mutta poikkeusluokkasi sisältää lähes aina jonkinlaisen viestin sekä mahdollisesti jonkinlaisen virhekoodin. Lisäksi poikkeusolio voi sisältää lisätietoa virheen syystä haluamassasi muodossa. 681

14 C++ Ohjelmoijan käsikirja Voimme määritellä oman poikkeusluokkamme. Kirjoitetaan se nimeltään varsin yleiseen otsikkotiedostoon Ongelmat.h: // Ongelmat.h Poikkeusluokan määrittely #ifndef ONGELMAT_H #define ONGELMAT_H class Ongelma public: Ongelma(const char* pmjono = "Tässä on ongelma") : pviesti(pmjono) const char* mika() const return pviesti; private: const char* pviesti; ; #endif Tämä luokka määrittelee poikkeuksen kuvaavan olion, joka sisältää viestin, että törmättiin ongelmaan. Muodostinfunktion parametrille on määritelty oletusarvo, joten voit käyttää oletusmuodostinfunktiota luodaksesi olion, joka sisältää oletusviestin. Jäsenfunktio mika() palauttaa nykyisen viestin. Koska emme varaa muistia vapaasta muistista, oletuskopiomuodostin riittää tässä tapauksessa. Jotta poikkeusten käsittelyn mekanismi pysyy hallittavana, sinun tulee varmistaa, että poikkeusluokan jäsenfunktiot eivät muodosta poikkeuksia. Myöhemmin tässä luvussa näet, miten voit estää jäsenfunktiota muodostamasta poikkeusta. Kokeillaan, mitä tapahtuu, kun poikkeusolio muodostetaan. Kuten edellistenkin esimerkkien kohdalla muodostamme koodissa suoraan poikkeuksia, jotta voimme seurata, mitä tapahtuu eri tilanteissa. Varmistetaan ensin, että tiedämme, miten poikkeusolio muodostetaan. Kokeile itse - Poikkeusolion muodostaminen Voimme testata poikkeusluokkaamme hyvin yksinkertaisella esimerkillä, joka muodostaa silmukassa poikkeuksia: // Esimerkki 17.3 Muodostetaan poikkeusolio #include <iostream> #include "Ongelmat.h" using namespace std; 682 int main() for(int i = 0 ; i < 2 ; i++) if(i == 0) throw Ongelma(); else throw Ongelma("Kukaan ei ole vielä nähnyt tätä ongelmaa");

15 Ohjelman virheet ja poikkeusten käsittely catch(const Ongelma& t) cout << endl << "Poikkeus: " << t.mika(); return 0; Tämä tuottaa seuraavan tulostuksen: Poikkeus: Tässä on ongelma Poikkeus: Kukaan ei ole vielä nähnyt tätä ongelmaa Kuinka se toimii Muodostamme for-silmukassa kaksi poikkeusoliota. Ensimmäisen, joka sisältää oletusviestin, muodostaa Ongelma-luokan oletusmuodostinfunktio. Toinen poikkeusolio muodostetaan iflauseen else-osassa ja sisältää viestin, jonka välitämme muodostinfunktiolle parametrinä. catchlohko käsittelee molemmat poikkeusoliot. Pidä mielessä, että poikkeusolio kopioidaan aina kun se muodostetaan, joten jos et määrittele parametriä catch-lohkossa viittaukseksi, se kopioidaan toiseen kertaan - aivan tarpeettomasti. Tapahtumien järjestys poikkeusolion muodostamisessa on seuraava: olio kopioidaan ensiksi (luodaan tilapäinen olio) ja alkuperäinen olio tuhotaan tämän jälkeen, koska suoritus poistuu lohkosta ja olion näkyvyysalue päättyy. Kopio välitetään catch-käsittelijälle - viittauksena, jos parametri on viittausparametri. Jos haluat seurata näitä tapahtumia, lisää Ongelma-luokkaan kopiomuodostin ja tuhoajafunktio. Oikean catch-käsittelijän valinta Aikaisemmin mainitsimme, että -lohkon perässä olevat käsittelijät tutkitaan siinä järjestyksessä kuin ne koodissa ovat. Ensimmäinen käsittelijä, jonka tyyppi vastaa poikkeuksen tyyppiä, suoritetaan. Perustietotyyppejä (ei luokkatyyppejä) olevien poikkeusten kohdalla tyyppien tulee vastata toisiaan täydellisesti. Luokkaolioiden kohdalla voidaan mahdollisesti suorittaa automaattinen muunnos, jotta poikkeuksen tyyppi vastaa käsittelijän tyyppiä. Kun parametrin (käsittelijän) tyyppiä verrataan poikkeuksen tyyppiin, seuraavat ajatellaan vastaaviksi: Parametrin tyyppi on const-määrettä lukuun ottamatta sama kuin poikkeuksen tyyppi. Parametrin tyyppi on poikkeusluokkatyypin suora tai epäsuora kantaluokka tai viittaus poikkeusluokan suoraan tai epäsuoraan kantaluokkaan, kun constmäärettä ei huomioida. Poikkeus ja parametri ovat osoittimia ja poikkeuksen tyyppi voidaan muuntaa automaattisesti parametrin tyyppiin. const-määrettä ei huomioida tässäkään. Edellä luetellut mahdolliset tyypinmuunnokset vaikuttavat siihen, mihin järjestykseen käsittelijät sijoitetaan -lohkossa. Jos sinulla on useita käsittelijöitä poikkeuksille, joiden tyyppi on samassa luokkahierarkiassa, kaikkein alimmalla tasolla olevan periytetyn tyypin tulee olla ensin ja kaikkein ylimmällä tasolla olevan kantatyypin tulee olla viimeisenä. Jos käsittelijät ovat toisin päin, kantaluokkatyypin käsittelijä valitaan aina käsittelemään periytetyn luokan poikkeukset. Eli toisin sanoen, periytetyn tyypin käsittelijää ei suoriteta koskaan. 683

16 C++ Ohjelmoijan käsikirja Lisätään muutama uusi poikkeus Ongelma-luokan sisältämään otsikkotiedostoon käyttämällä Ongelma-luokkaa niiden kantaluokkana. Ongelmat.h-otsikkotiedosto näyttää lisäyksen jälkeen seuraavalta: // Ongelmat.h Poikkeusluokan määrittely #ifndef ONGELMAT_H #define ONGELMAT_H // Poikkeusten kantaluokka class Ongelma public: Ongelma(const char* pmjono = "Tässä on ongelma"); virtual ~Ongelma(); virtual const char* mika() const; private: const char* pviesti; ; // Periytetty poikkeusluokka class LisaOngelma : public Ongelma public: LisaOngelma(const char* pmjono = "Lisää ongelmia"); ; // Periytetty poikkeusluokka class IsoOngelma : public LisaOngelma public: IsoOngelma(const char* pmjono = "Todella suuri ongelma"); ; #endif Huomaa, että kantaluokan mika()-jäsenfunktio ja tuhoajafunktio ovat esitellyt virtuaalisiksi. Funktio mika() on tämän jälkeen virtuaalinen kaikissa Ongelma-luokasta periytetyissä luokissa. Tässä sillä ei ole juurikaan merkitystä, mutta on hyvä totuttautua tapaan, että kantaluokan tuhoajafunktio esitellään virtuaaliseksi. Oletusviestiä lukuun ottamatta periytetty luokka ei lisää kantaluokkaan mitään. Usein pelkkää eri luokan nimeä käytetään erottamaan eri ongelmat toisistaan. Kun törmätään tietyn tyyppiseen ongelmaan, muodostetaan vain sen tyyppinen poikkeus; luokan sisällön ei tarvitse olla erilainen. Käyttämällä erilaista catch-lohkoa jokaisen luokkatyypin kohdalla voidaan erottaa ongelmat toisistaan. Kolmen luokan jäsenfunktioiden määrittelyt voidaan kirjoittaa Ongelmat.cpp-tiedostoon: // Ongelmat.cpp #include "Ongelmat.h" 684 // Ongelma-luokan muodostinfunktio Ongelma::Ongelma(const char* pmjono) : pviesti(pmjono)

17 Ohjelman virheet ja poikkeusten käsittely // Ongelma-luokan tuhoajafunktio Ongelma::~Ongelma() // Palauttaa viestin const char* Ongelma::mika() const return pviesti; // LisaOngelma-luokan muodostinfunktio LisaOngelma::LisaOngelma(const char* pmjono) : Ongelma(pMjono) // IsoOngelma-luokan muodostinfunktio IsoOngelma::IsoOngelma(const char* pmjono) : LisaOngelma(pMjono) Voimme nyt kokeilla näitä luokkia esimerkin avulla. Kokeile itse - Hierarkian poikkeusluokkien muodostaminen Tämä ohjelma muodostaa Ongelma-, LisaOngelma- ja IsoOngelma-tyyppiset poikkeukset ja käsittelee ne: // Esimerkki 17.4 Luokkahierarkian poikkeusten muodostaminen #include <iostream> #include "Ongelmat.h" using namespace std; int main() Ongelma ongelma; LisaOngelma lisaongelma; IsoOngelma isoongelma; cout << endl; for(int i = 0 ; i < 7 ; i++) if(i < 3) throw ongelma; if(i < 5) throw lisaongelma; else throw isoongelma; catch(isoongelma& ro) cout << " IsoOngelmaa käsitellään: " << ro.mika() << endl; catch(lisaongelma& ro) cout << " LisaOngelmaa käsitellään: " << ro.mika() << endl; 685

18 C++ Ohjelmoijan käsikirja catch(ongelma& ro) cout << "Ongelmaa käsitellään: " << ro.mika() << endl; cout << "Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on " << i << endl; cout << endl; return 0; Esimerkin tulostus näyttää seuraavalta: Ongelmaa käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 Ongelmaa käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1 Ongelmaa käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 LisaOngelmaa käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 LisaOngelmaa käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 IsoOngelmaa käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 IsoOngelmaa käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 6 Kuinka se toimii Kun olemme luoneet yhden olion jokaisesta kolmesta luokasta, suoritamme for-silmukan, joka sisältää seuraavan -lohkon: if(i < 3) throw ongelma; if(i < 5) throw lisaongelma; else throw isoongelma; 686 Silmukkamuuttujan i arvoille, jotka ovat pienempiä kuin 3, muodostamme Ongelma-tyyppisen poikkeuksen. Kun i on 3 tai 4, muodostamme LisaPoikkeus-tyyppisen poikkeuksen. Kun i on 5 tai suurempi, muodostamme IsoOngelma-tyyppisen poikkeuksen. Meillä on käsittelijä jokaiselle luokkatyypille. Ensimmäinen on IsoOngelma-tyyppisille poikkeuksille: catch(isoongelma& ro) cout << " IsoOngelmaa käsitellään: " << ro.mika() << endl;

19 Ohjelman virheet ja poikkeusten käsittely Muut käsittelijät ovat aivan samanlaiset, niiden viestit ovat vain hieman erilaiset. Funktio mika() palauttaa viestin myös kahden periytetyn käsittelijän kohdalla. Huomaa, että kaikkien catch-lohkojen parametrit ovat viittauksia, kuten oli edellisessäkin esimerkissä. Tällä vältetään toisen kopion muodostaminen poikkeusoliosta. Seuraavassa esimerkissä näemme toisenkin hyvän syyn, miksi käsittelijän parametrin tulisi aina olla viittaus. Kukin käsittelijä tulostaa muodostetun olion sisältämän viestin. Tulostuksesta huomaat, että oikeaa käsittelijää kutsutaan tietyntyyppisen poikkeuksen kohdalla. Käsittelijöiden järjestys on tässä tärkeä, johtuen tavasta, jolla poikkeusten tyyppiä verrataan käsittelijän tyyppiin ja koska esimerkkimme luokat ovat samassa luokkahierarkiassa. Tarkastellaan tätä seuraavaksi hieman tarkemmin. Periytetyn luokan poikkeuksen käsittely kantaluokan käsittelijällä Koska periytetyn luokan poikkeukset muunnetaan automaattisesti kantaluokan tyyppisiksi etsittäessä oikeaa käsittelijää, voimme käsitellä kaikki edellisen esimerkin poikkeukset yhdessä ja samassa käsittelijässä. Muutetaan edellistä esimerkkiä nyt hieman. Kokeile itse - Kantaluokan käsittelijän käyttö Sinun tarvitsee vain poistaa (tai kommentoida) kaksi periytettyjen luokkien käsittelijää edellisestä esimerkistä: // Esimerkki 17.5 Poikkeuksen käsittely kantaluokan käsittelijällä #include <iostream> #include "Ongelmat.h" using namespace std; int main() Ongelma ongelma; LisaOngelma lisaongelma; IsoOngelma isoongelma; cout << endl; for(int i = 0 ; i < 7 ; i++) if(i < 3) throw ongelma; if(i < 5) throw lisaongelma; else throw isoongelma; 687

20 C++ Ohjelmoijan käsikirja catch(ongelma& ro) // Ainoastaan kantaluokan käsittelijä cout << "Ongelmaa käsitellään: " << ro.mika() << endl; cout << "Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on " << i << endl; cout << endl; return 0; Ohjelman tulostus näyttää seuraavalta: Ongelmaa käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 Ongelmaa käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1 Ongelmaa käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 Ongelmaa käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 Ongelmaa käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 Ongelmaa käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 Ongelmaa käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on Kuinka se toimii Ongelma&-tyyppinen käsittelijä käsittelee nyt kaikki poikkeukset. Jos catch-lohkon parametri on viittaus kantaluokkaan, kaikki periytettyjen luokkien poikkeukset käsitellään sillä. Eli kun tulostus väittää, että Ongelmaa käsitellään, neljä viimeistä ovat itse asiassa Ongelma-luokasta periytettyjä poikkeuksia. Koska dynaaminen tyyppi säilytetään, kun poikkeus välitetään viittauksena, saat dynaamisen tyypin selville typeid()-operaattorilla, jolla voit sen myös tulostaa. Muuta käsittelijän koodi muotoon: catch(ongelma& ro) cout << typeid(ro).name() << " oliota käsitellään: " << ro.mika() << endl; Joissakin kääntäjissä suorituksenaikainen tyypintunnistus ei ole oletusarvoisesti päällä, joten jos tämä ei toimi, tarkista kääntäjän asetukset. Nämä muutokset koodiin havainnollistavat, että periytetyn luokan poikkeukset säilyttävät dynaamisen tyyppinsä, vaikka käytetäänkin viittausta kantaluokkaan. Palauta mieleen, että typeid()-operaattori palauttaa type_info-luokan olion, jonka name()-jäsenfunktio palauttaa luokan nimen const char* -tyyppisenä. Tämän ohjelmaversion tulostus näyttää seuraavalta: class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1

21 class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 class LisaOngelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 class LisaOngelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 class IsoOngelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 class IsoOngelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 6 Ohjelman virheet ja poikkeusten käsittely Nyt voit kokeilla muuttaa käsittelijän parametrin tyypin Ongelma-tyyppiseksi, eli poikkeus välitetään nyt arvoparametrinä eikä viittausparametrinä: catch(ongelma o) cout << typeid(o).name() << " oliota käsitellään: " << o.mika() << endl; Kun suoritat ohjelman tämän version, saat tulostuksen: class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1 class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 class Ongelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 class Ongelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 class Ongelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 6 Ongelma-tyyppinen käsittelijä valitaan edelleen periytetyn luokan olion kohdalla, mutta dynaamista tyyppiä ei enää säilytetä. Tämä siksi, että parametri alustetaan käyttämällä kantaluokan kopiomuodostinta, joten kaikki periytettyyn luokkaan kuuluvat ominaisuudet menetetään. Tällaisessa tilanteessa säilytetään ainoastaan alkuperäisen periytetyn luokan olion kantaluokan aliolio. Kaikki periytetyn luokan jäsenet poistetaan oliosta. Tämä on esimerkki olion paloittelemisesta. Paloittelu tehdään, koska kantaluokan kopiomuodostin ei tiedä mitään periytetystä luokasta. Olion paloittelu on varsin yleinen virheiden lähde, kun olioita välitetään arvoparametreinä. Paloittelu voi tapahtua sekä tavallisten funktioiden että poikkeusten käsittelijöiden kohdalla. Sinun tulisi aina käyttää viittausparametrejä catch-lohkoissasi. Poikkeuksen uudelleenmuodostaminen Kun käsittelijä käsittelee poikkeusta, se voi muodostaa poikkeuksen uudelleen, jotta ulomman -lohkon käsittelijä voi sen käsitellä. Voit muodostaa nykyisen poikkeuksen uudelleen kirjoittamalla pelkästään avainsanan throw: throw; // Muodostetaan poikkeus uudelleen 689

22 C++ Ohjelmoijan käsikirja Tämä muodostaa nykyisen poikkeusolion uudelleen kopioimatta sitä. Poikkeus voidaan muodostaa uudelleen esimerkiksi silloin, kun käsittelijä huomaa, että poikkeus tulisi välittää ulommalle -lohkolle. Voit myös haluta rekisteröidä ohjelman kohdan, jossa poikkeus muodostettiin, ja välittää se edelleen esimerkiksi ohjelman johonkin yleiseen osaan, kuten main()-funktioon. // Ulompi -lohko // Sisempi -lohko if( ) throw ex; catch(extyyppi ex) throw; catch(atyyppi ex) catch(extyyppi ex) // Käsitellään ex Tämä käsittelijä käsittelee sisemmässä -lohkossa muodostetun ex-poikkeuksen. Tämä lause muodostaa ex- poikkeuksen uudelleen kopioimatta sitä, joten se voidaan käsitellä ulomman -lohkon käsittelijässä. Huomaa, että jos muodostat poikkeuksen uudelleen sisemmässä -lohkossa, sisemmän lohkon käsittelijät eivät voi sitä kuitenkaan käsitellä. Kun käsittelijä on suorituksessa, muodostettu poikkeus (mukaan lukien nykyinen poikkeus) tulee käsitellä -lohkossa, jonka sisällä nykyinen käsittelijä sijaitsee. Tätä havainnollistetaan yllä olevassa kaaviossa. Se, että uudelleen muodostettua poikkeusta ei kopioida, on tärkeää, varsinkin silloin, kun poikkeus on periytetyn luokan olio, joka alusti kantaluokan viittausparametrin. Havainnollistetaan tätä esimerkin avulla. Kokeile itse - Poikkeuksen uudelleenmuodostaminen Voimme muodostaa joitakin Ongelma-, LisaOngelma- ja IsoOngelma-poikkeusolioita ja muodostaa osan niistä uudelleen: // Esimerkki 17.6 Poikkeuksen uudelleenmuodostaminen #include <iostream> #include "Ongelmat.h" using namespace std; 690 int main() Ongelma ongelma;

23 Ohjelman virheet ja poikkeusten käsittely LisaOngelma lisaongelma; IsoOngelma isoongelma; cout << endl; for(int i = 0 ; i < 7 ; i++) if(i < 3) throw ongelma; if(i < 5) throw lisaongelma; else throw isoongelma; catch(ongelma& ro) if(typeid(ro) == typeid(ongelma)) cout << "Ongelma-oliota käsitellään: " << ro.mika() << endl; else throw; // Muodostetaan nykyinen poikkeus uudelleen catch(ongelma& ro) cout << typeid(ro).name() << " oliota käsitellään: " << ro.mika() << endl; cout << "Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on " << i << endl; cout << endl; return 0; Ohjelma tulostaa: Ongelma-oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 Ongelma-oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1 Ongelma-oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 class LisaOngelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 class LisaOngelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 class IsoOngelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 class IsoOngelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 6 691

24 C++ Ohjelmoijan käsikirja Kuinka se toimii for-silmukka toimii samaan tapaan kuin edellisessäkin esimerkissä, mutta tällä kertaa -lohkon sisällä on toinen -lohko. Poikkeusoliot muodostetaan sisemmässä -lohkossa: if(i < 3) throw ongelma; if(i < 5) throw lisaongelma; else throw isoongelma; Tämä muodostaa samat poikkeusoliot samassa järjestyksessä kuin edellinenkin esimerkki. Käsittelijä käsittelee ne kaikki, koska sen parametri on viittaus kantaluokkaan: catch(ongelma& ro) if(typeid(ro) == typeid(ongelma)) cout << "Ongelma-oliota käsitellään: " << ro.mika() << endl; else throw; // Muodostetaan nykyinen poikkeus uudelleen Tämä käsittelijä käsittelee kaikki Ongelma-tyyppiset poikkeukset ja kaikki Ongelma-luokasta periytetyt poikkeukset. if-lause testaa välitetyn olion tyypin ja tulostaa tulostuksen, jos sen tyyppi oli Ongelma. Muun tyyppisten poikkeusten kohdalla se muodostaa poikkeuksen uudelleen. Voit erottaa tämän catch-lohkon tulostuksen siitä, että se ei ala sanalla class. Uudelleen muodostettu poikkeus voidaan sitten käsitellä ulomman -lohkon käsittelijässä: catch(ongelma& ro) cout << typeid(ro).name() << " oliota käsitellään: " << ro.mika() << endl; 692 Parametri on myös tässä viittaus Ongelma-olioon, joten se käsittelee kaikki periytettyjen luokkien oliot. Tulostuksesta näet, että se käsittelee uudelleen muodostetut poikkeukset, jotka ovat yhä hyvässä kunnossa. Nyt saatat kuvitella, että sisemmän -lohkon käsittelijässä oleva throw;-lause on sama kuin seuraava lause: throw ro; // Muodostetaan nykyinen poikkeus uudelleen Olemmehan vain muodostamassa poikkeuksen uudelleen, vai mitä? Vastaus on että ei ole; tässä on itse asiassa suurikin ero. Tee ohjelman koodiin tämä muutos ja suorita se uudelleen. Saat seuraavanlaisen tulostuksen: Ongelma-oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 Ongelma-oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1

25 Ongelma-oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 class Ongelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 class Ongelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 class Ongelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 class Ongelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 6 Ohjelman virheet ja poikkeusten käsittely Poikkeuksen muodostaminen tällä tavalla saa aikaan poikkeuksen kopioinnin Ongelma-luokan kopiomuodostimella. Tässä on jälleen olion paloittelemisongelma. Periytetyn luokan olion osa leikataan pois, joten jäljelle jää tässä tapauksessa vain kantaluokan aliolio. Tulostuksesta huomaat, että typeid()-operaattori tunnistaa kaikki poikkeukset Ongelma-tyyppisiksi. Kaikkien poikkeusten käsittely Voit käyttää kolmea pistettä catch-lohkon parametrin määrittelyssä. Tämä tarkoittaa, että lohko käsittelee kaikki poikkeukset: catch() // Koodi, joka käsittelee kaikki poikkeukset Tämä catch-lohko käsittelee kaiken tyyppiset poikkeukset, joten tällaisten käsittelijöiden tulee aina olla -lohkon käsittelijöistä viimeisenä. Tällöin sinulla ei tietystikään ole mitään tietoa, mikä poikkeus on, mutta voit ainakin estää ohjelman suorituksen päättymisen siksi, että poikkeusta ei käsitellä. Huomaa, että vaikka et tiedä poikkeuksesta mitään, voit muodostaa poikkeuksen uudelleen, kuten teimme edellisessä esimerkissä. Kokeile itse - Minkä tahansa poikkeuksen käsittely Voimme muuttaa edellistä esimerkkiä siten, että sisemmän -lohkon kaikki poikkeukset käsitellään. Tämä tapahtuu lisäämällä kolme pistettä parametrin tilalle: // Esimerkki 17.7 Minkä tahansa poikkeuksen käsittely #include <iostream> #include "Ongelmat.h" using namespace std; int main() Ongelma ongelma; LisaOngelma lisaongelma; IsoOngelma isoongelma; cout << endl; for(int i = 0 ; i < 7 ; i++) 693

26 C++ Ohjelmoijan käsikirja if(i < 3) throw ongelma; if(i < 5) throw lisaongelma; else throw isoongelma; catch() cout << "Käsittelemme jotakin! Muodostetaan se uudelleen." << endl; throw; // Muodostetaan nykyinen poikkeus uudelleen catch(ongelma& ro) cout << typeid(ro).name() << " oliota käsitellään: " << ro.mika() << endl; cout << "Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on " << i << endl; cout << endl; return 0; Tulostus näyttää nyt tältä: Käsittelemme jotakin! Muodostetaan se uudelleen. class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 0 Käsittelemme jotakin! Muodostetaan se uudelleen. class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 1 Käsittelemme jotakin! Muodostetaan se uudelleen. class Ongelma oliota käsitellään: Tässä on ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 2 Käsittelemme jotakin! Muodostetaan se uudelleen. class LisaOngelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 3 Käsittelemme jotakin! Muodostetaan se uudelleen. class LisaOngelma oliota käsitellään: Lisää ongelmia Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 4 Käsittelemme jotakin! Muodostetaan se uudelleen. class IsoOngelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 5 Käsittelemme jotakin! Muodostetaan se uudelleen. class IsoOngelma oliota käsitellään: Todella suuri ongelma Silmukan loppu (kaikkien catch-lohkojen jälkeen) - i on 6 694

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä 812347A Olio-ohjelmointi, 2015 syksy 2. vsk X Poikkeusten käsittelystä Sisältö 1. Yleistä poikkeusten käsittelystä 2. Poikkeuskäsittelyn perusteita C++:ssa 3. Standardissa määritellyt poikkeukset 4. Poikkeusvarmuus

Lisätiedot

Virtuaalifunktiot ja polymorfismi

Virtuaalifunktiot ja polymorfismi Virtuaalifunktiot ja polymorfismi 16 Virtuaalifunktiot ja polymorfismi Polymorfismi on niin tehokas olio-ohjelmoinnin ominaisuus, että tulet varmastikin käyttämään sitä lähes kaikissa C++-ohjelmissasi.

Lisätiedot

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta C++ - perusteet Java-osaajille luento 5/7: operaattoreiden ylikuormitus, oliotaulukko, parametrien oletusarvot, komentoriviparametrit, constant, inline, Operaattoreiden ylikuormitus Operaattoreiden kuormitus

Lisätiedot

Periytyminen. Luokat ja olio-ohjelmointi

Periytyminen. Luokat ja olio-ohjelmointi Periytyminen 15 Periytyminen Tässä luvussa käsittelemme aihetta, joka on olio-ohjelmoinnin kaikkein tärkein osa - periytyvyys. Periytyvyyden avulla voimme luoda uusia luokkia uudelleenkäyttämällä ja laajentamalla

Lisätiedot

Luokan operaatiot. Osoittimet ja viittaukset luokan olioihin

Luokan operaatiot. Osoittimet ja viittaukset luokan olioihin Luokan operaatiot 13 Luokan operaatiot Luokkien olioiden luomiseen ja tuhoamiseen liittyy monia hienouksia, joista sinun tulee olla selvillä, jotta luokkiesi olioiden operaatiot toimivat turvallisesti

Lisätiedot

815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset

815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset Harjoituksen aiheena ovat aliohjelmat ja abstraktit tietotyypit sekä olio-ohjelmointi. Tehtävät tehdään C-, C++- ja Java-kielillä.

Lisätiedot

Osoitin ja viittaus C++:ssa

Osoitin ja viittaus C++:ssa Osoitin ja viittaus C++:ssa Osoitin yksinkertaiseen tietotyyppiin Osoitin on muuttuja, joka sisältää jonkin toisen samantyyppisen muuttujan osoitteen. Ohessa on esimerkkiohjelma, jossa määritellään kokonaislukumuuttuja

Lisätiedot

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 3 vastaukset Harjoituksen aiheena ovat imperatiivisten kielten muuttujiin liittyvät kysymykset. Tehtävä 1. Määritä muuttujien max_num, lista,

Lisätiedot

815338A Ohjelmointikielten periaatteet

815338A Ohjelmointikielten periaatteet 815338A Ohjelmointikielten periaatteet 2015-2016 VIII Poikkeusten ja tapahtumien käsittely Sisältö 1. Poikkeusten käsittelyn käsitteitä ja suunnittelukriteerejä 2. Poikkeusten käsittely C++:ssa 3. Poikkeusten

Lisätiedot

Mallit standardi mallikirjasto parametroitu tyyppi

Mallit standardi mallikirjasto parametroitu tyyppi Mallit 18 Mallit Malli on tehokas mekanismi uusien luokkien generoimiseksi automaattisesti. Standardikirjaston suuri osa, standardi mallikirjasto, rakentuu kokonaan mallien määrittelymahdollisuuden ympärille,

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2009 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2009 1 / 28 Puhelinluettelo, koodi def lue_puhelinnumerot(): print "Anna lisattavat nimet ja numerot." print

Lisätiedot

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista Sisällys 1. Omat operaatiot Yleistä operaatioista. Mihin operaatioita tarvitaan? Oman operaation määrittely. Yleisesti, nimeäminen ja hyvä ohjelmointitapa, määreet, parametrit ja näkyvyys. HelloWorld-ohjelma

Lisätiedot

Operaattoreiden uudelleenmäärittely

Operaattoreiden uudelleenmäärittely Operaattoreiden uudelleenmäärittely 14 Operaattoreiden uudelleenmäärittely Tässä luvussa käsittelemme, kuinka voit lisätä toiminnallisuutta luokkiisi, jotta ne toimivat enemmän C++:n perustietotyyppien

Lisätiedot

Olio-ohjelmointi Poikkeusten käsittelystä. 1. Johdanto

Olio-ohjelmointi Poikkeusten käsittelystä. 1. Johdanto Olio-ohjelmointi Poikkeusten käsittelystä Virheiden käsittely liittyy olennaisesti kaikkeen ohjelmointiin. Monissa sovelluksissa virhetilanteiden käsittelemiseen liittyvää koodia on merkittävä osuus koko

Lisätiedot

Luokassa määriteltävät jäsenet ovat pääasiassa tietojäseniä tai aliohjelmajäseniä. Luokan määrittelyyn liittyvät varatut sanat:

Luokassa määriteltävät jäsenet ovat pääasiassa tietojäseniä tai aliohjelmajäseniä. Luokan määrittelyyn liittyvät varatut sanat: 1. Luokan jäsenet Luokassa määriteltävät jäsenet ovat pääasiassa tietojäseniä tai aliohjelmajäseniä. Luokan määrittelyyn liittyvät varatut sanat: class luokan_nimi tyypit: enum, struct, class, typedef

Lisätiedot

14. Poikkeukset 14.1

14. Poikkeukset 14.1 14. Poikkeukset 14.1 Sisällys Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla poikkeuksella? Poikkeusten heittäminen.

Lisätiedot

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto Sisällys 14. Poikkeukset Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla poikkeuksella? Poikkeusten heittäminen.

Lisätiedot

1. Omat operaatiot 1.1

1. Omat operaatiot 1.1 1. Omat operaatiot 1.1 Sisällys Yleistä operaatioista. Mihin operaatioita tarvitaan? Oman operaation määrittely. Yleisesti, nimeäminen ja hyvä ohjelmointitapa, määreet, parametrit ja näkyvyys. HelloWorld-ohjelma

Lisätiedot

11. Javan toistorakenteet 11.1

11. Javan toistorakenteet 11.1 11. Javan toistorakenteet 11.1 Sisällys Laskuri- ja lippumuuttujat. Sisäkkäiset silmukat. Tyypillisiä ohjelmointivirheitä: Silmukan rajat asetettu kierroksen verran väärin. Ikuinen silmukka. Silmukoinnin

Lisätiedot

12 Mallit (Templates)

12 Mallit (Templates) 12 Mallit (Templates) Malli on määrittely, jota käyttämällä voidaan luoda samankaltaisten aliohjelmien ja luokkien perheitä. Malli on ohje kääntäjälle luoda geneerisestä tyyppiriippumattomasta ohjelmakoodista

Lisätiedot

T Olio-ohjelmointi Osa 3: Luokka, muodostin ja hajotin, this-osoitin Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

T Olio-ohjelmointi Osa 3: Luokka, muodostin ja hajotin, this-osoitin Jukka Jauhiainen OAMK Tekniikan yksikkö 2010 11. Luokka Opetellaan seuraavaksi, miten omia luokkia kirjoitetaan. Aikaisemmin olikin jo esillä, että luokka on tietorakenne, joka sisältää sekä tiedot (attribuutit) että niitä käsittelevät aliohjelmat

Lisätiedot

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen Metodit Metodien määrittely Metodin parametrit ja paluuarvo Metodien suorittaminen eli kutsuminen Metodien kuormittaminen 1 Mikä on metodi? Metodi on luokan sisällä oleva yhteenkuuluvien toimintojen kokonaisuus

Lisätiedot

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto Sisällys 14. Poikkeukset Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Miten varautua poikkeukseen metodissa? Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla

Lisätiedot

T740103 Olio-ohjelmointi Osa 5: Periytyminen ja polymorfismi Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

T740103 Olio-ohjelmointi Osa 5: Periytyminen ja polymorfismi Jukka Jauhiainen OAMK Tekniikan yksikkö 2010 12. Periytyminen Johdantoa Käytännössä vähänkään laajemmissa ohjelmissa joudutaan laatimaan useita luokkia, joiden pitäisi pystyä välittämään tietoa toisilleen. Ohjelmien ylläpidon kannalta olisi lisäksi

Lisätiedot

Poikkeustenkäsittely

Poikkeustenkäsittely 1 Poikkeustenkäsittely Mitä poikkeustenkäsittely tarkoittaa? Poikkeuksen käsitteleminen Poikkeusluokkien hierarkia Poikkeuksen heittäminen 1 Mitä poikkeustenkäsittely tarkoittaa? Poikkeus (Exception) on

Lisätiedot

14. Poikkeukset 14.1

14. Poikkeukset 14.1 14. Poikkeukset 14.1 Sisällys Johdanto. Tarkistettavat ja tarkistamattomat poikkeukset. Miten varautua poikkeukseen metodissa? Poikkeusten tunnistaminen ja sieppaaminen try-catchlauseella. Mitä tehdä siepatulla

Lisätiedot

Kääntäjän virheilmoituksia

Kääntäjän virheilmoituksia OHJ-1101 Ohjelmointi 1e 2008-09 1 Kääntäjän virheilmoituksia Kun progvh2 ohjelma käännetään antaa tutg++ seuraavat virheilmoitukset ja varoitukset: proffa> tutg++ progvh2.cc progvh2.cc:29:13: warning:

Lisätiedot

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3 15. Lohkot 15.1 Sisällys Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 15.2 Lohkot Aaltosulkeet

Lisätiedot

Sisällys. 15. Lohkot. Lohkot. Lohkot

Sisällys. 15. Lohkot. Lohkot. Lohkot Sisällys 15. Lohkot Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 15.1 15.2 Lohkot Aaltosulkeet

Lisätiedot

Olio-ohjelmointi Virhetilanteiden käsittely

Olio-ohjelmointi Virhetilanteiden käsittely Olio-ohjelmointi 2016 Virhetilanteiden käsittely Poikkeustilanteet n Java-järjestelmässä voidaan ottaa kiinni ohjelman suoritusaikana tapahtuvia virhetilanteita, joita ei saada kiinni tavanomaisilla ohjausrakenteilla

Lisätiedot

Luokat. Luokat ja olio-ohjelmointi

Luokat. Luokat ja olio-ohjelmointi Luokat 12 Luokat Tässä luvussa laajennamme edellisessä luvussa käsittelemäämme struktuurityyppiä ja siirrymme yhteen C++-ohjelmoijan kaikkein tärkeimmistä välineistä: luokkiin. Käsittelemme myöskin joitakin

Lisätiedot

C++11 Syntaksi. Jari-Pekka Voutilainen Jari-Pekka Voutilainen: C++11 Syntaksi

C++11 Syntaksi. Jari-Pekka Voutilainen Jari-Pekka Voutilainen: C++11 Syntaksi 1 C++11 Syntaksi Jari-Pekka Voutilainen 13.4.2012 2 Range-for Iteroi säiliön kaikki alkiot for-silmukassa. Säiliöltä vaaditaan begin- ja end-iteraattorit. Pätee kaikille C++11 STL-säiliöille, taulukoille,

Lisätiedot

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3 16. Lohkot 16.1 Sisällys Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 16.2 Lohkot Kaarisulut

Lisätiedot

C++ rautaisannos. Kolme tapaa sanoa, että tulostukseen käytetään standardikirjaston iostreamosassa määriteltyä, nimiavaruuden std oliota cout:

C++ rautaisannos. Kolme tapaa sanoa, että tulostukseen käytetään standardikirjaston iostreamosassa määriteltyä, nimiavaruuden std oliota cout: C++ rautaisannos Kolme tapaa sanoa, että tulostukseen käytetään standardikirjaston iostreamosassa määriteltyä, nimiavaruuden std oliota cout: # include #include main ( ) main (

Lisätiedot

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä Sisällys 11. Javan toistorakenteet Laskuri- ja lippumuuttujat.. Tyypillisiä ohjelmointivirheitä: Silmukan rajat asetettu kierroksen verran väärin. Ikuinen silmukka. Silmukoinnin lopettaminen break-lauseella.

Lisätiedot

11/20: Konepelti auki

11/20: Konepelti auki Ohjelmointi 1 / syksy 2007 11/20: Konepelti auki Paavo Nieminen nieminen@jyu.fi Tietotekniikan laitos Informaatioteknologian tiedekunta Jyväskylän yliopisto Ohjelmointi 1 / syksy 2007 p.1/11 Tämän luennon

Lisätiedot

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1 12. Javan toistorakenteet 12.1 Sisällys Yleistä toistorakenteista. Laskurimuuttujat. While-, do-while- ja for-lauseet. Laskuri- ja lippumuuttujat. Tyypillisiä ohjelmointivirheitä. Silmukan rajat asetettu

Lisätiedot

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely Poikkeukset Poikkeuksella tarkoitetaan yllättävää ajonaikaista tilannetta, joka

Lisätiedot

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1 12. Javan toistorakenteet 12.1 Sisällys Yleistä toistorakenteista. Laskurimuuttujat. While-, do-while- ja for-lauseet. Laskuri- ja lippumuuttujat. Tyypillisiä ohjelmointivirheitä. Silmukan rajat asetettu

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 20. huhtikuuta 2018 Vastaa kaikkiin tehtäviin. Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä.

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 28.2.2011 T-106.1208 Ohjelmoinnin perusteet Y 28.2.2011 1 / 46 Ohjelmointiprojektin vaiheet 1. Määrittely 2. Ohjelman suunnittelu (ohjelman rakenne ja ohjelman

Lisätiedot

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa(); Sisällys 7. Oliot ja viitteet Olio Java-kielessä. Olion luominen, elinikä ja tuhoutuminen. Viitteiden käsittelyä: sijoitus, vertailu ja varautuminen null-arvoon. Viite metodin paluuarvona.. 7.1 7.2 Olio

Lisätiedot

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1 15. Ohjelmoinnin tekniikkaa 15.1 Sisällys For-each-rakenne. Lueteltu tyyppi enum. Override-annotaatio. Geneerinen ohjelmointi. 15.2 For-each-rakenne For-rakenteen variaatio taulukoiden ja muiden kokoelmien

Lisätiedot

Tehtävä 1. TL5302 Olio-ohjelmointi Koe Malliratkaisuja. Tässä sekä a)- että b)-kohdan toimiva ratkaisu:

Tehtävä 1. TL5302 Olio-ohjelmointi Koe Malliratkaisuja. Tässä sekä a)- että b)-kohdan toimiva ratkaisu: TL5302 Olio-ohjelmointi Koe 19.4.2005 Malliratkaisuja Tehtävä 1 Tässä sekä a)- että b)-kohdan toimiva ratkaisu: #include using namespace std; int main() int taul[5]=1,2,3,4,5; int *p,&r=taul[0];

Lisätiedot

Periytymisen käyttö C++:ssa

Periytymisen käyttö C++:ssa 19 Periytymisen käyttö C++:ssa Periytymisessä voi osoitin tai viittaus kantaluokkatyyppiin viitata johdetun luokkatyypin olioon. Ohjelmamme voidaan sitten kirjoittaa käsittelemään näitä osoittimia tai

Lisätiedot

11. oppitunti III. Viittaukset. Osa. Mikä on viittaus?

11. oppitunti III. Viittaukset. Osa. Mikä on viittaus? Osa III 11. oppitunti Viittaukset Kahdessa viime luvussa opit käyttämään osoittimia kohteiden käsittelyyn vapaalla muistialueella sekä viittaamaan noihin kohteisiin epäsuorasti. Tässä luvussa käsiteltävät

Lisätiedot

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa. Taulukot C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa. Taulukon muuttujilla (muistipaikoilla) on yhteinen nimi. Jokaiseen yksittäiseen

Lisätiedot

Tietueet. Tietueiden määrittely

Tietueet. Tietueiden määrittely Tietueet Tietueiden määrittely Tietue on tietorakenne, joka kokoaa yhteen eri tyyppistä tietoa yhdeksi asiakokonaisuudeksi. Tähän kokonaisuuteen voidaan viitata yhteisellä nimellä. Auttaa ohjelmoijaa järjestelemään

Lisätiedot

Harjoitus 7. 1. Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Harjoitus 7. 1. Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti: Harjoitus 7 1. Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti: class Lintu //Kentät private int _siivenpituus; protected double _aivojenkoko; private bool _osaakolentaa; //Ominaisuudet public int

Lisätiedot

Geneeriset luokat. C++ - perusteet Java-osaajille luento 6/7: Template, tyyppi-informaatio, nimiavaruudet. Geneerisen luokan käyttö.

Geneeriset luokat. C++ - perusteet Java-osaajille luento 6/7: Template, tyyppi-informaatio, nimiavaruudet. Geneerisen luokan käyttö. Geneeriset luokat C++ - perusteet Java-osaajille luento 6/7: Template, tyyppi-informaatio, nimiavaruudet Geneerinen luokka tarkoittaa parametroitua luokkamallia, jonka avulla voidaan muodostaa useita,

Lisätiedot

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset 815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 2 vastaukset Harjoituksen aiheena on BNF-merkinnän käyttö ja yhteys rekursiivisesti etenevään jäsentäjään. Tehtävä 1. Mitkä ilmaukset seuraava

Lisätiedot

Harjoitustyö: virtuaalikone

Harjoitustyö: virtuaalikone Harjoitustyö: virtuaalikone Toteuta alla kuvattu virtuaalikone yksinkertaiselle olio-orientoituneelle skriptauskielelle. Paketissa on testaamista varten mukana kaksi lyhyttä ohjelmaa. Ohjeita Noudata ohjelman

Lisätiedot

Sisältö. 2. Taulukot. Yleistä. Yleistä

Sisältö. 2. Taulukot. Yleistä. Yleistä Sisältö 2. Taulukot Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko operaation parametrina. Taulukko ja HelloWorld-ohjelma. Taulukko paluuarvona. 2.1 2.2 Yleistä

Lisätiedot

Python-ohjelmointi Harjoitus 5

Python-ohjelmointi Harjoitus 5 Python-ohjelmointi Harjoitus 5 TAVOITTEET Kerrataan silmukkarakenteen käyttäminen. Kerrataan jos-ehtorakenteen käyttäminen. Opitaan if else- ja if elif else-ehtorakenteet. Matematiikan sisällöt Tehtävät

Lisätiedot

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä 12.1 12.2 12.3 12.4

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä 12.1 12.2 12.3 12.4 Sisällys 12. Näppäimistöltä lukeminen Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä.. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit. Scanner-luokka.

Lisätiedot

Sisällys. 16. Lohkot. Lohkot. Lohkot

Sisällys. 16. Lohkot. Lohkot. Lohkot Sisällys 16. ohkot Tutustutaan lohkoihin. Muuttujien ja vakioiden näkyvyys sekä elinikä erityisesti operaation lohkossa. Nimikonfliktit. Muuttujat operaation alussa vai myöhemmin? 16.1 16.2 ohkot aarisulut

Lisätiedot

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit IDL - proseduurit 25. huhtikuuta 2017 Viimeksi käsiteltiin IDL:n interaktiivista käyttöä, mutta tämä on hyvin kömpelöä monimutkaisempia asioita tehtäessä. IDL:llä on mahdollista tehdä ns. proseduuri-tiedostoja,

Lisätiedot

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014 18. syyskuuta 2014 IDL - proseduurit Viimeksi käsiteltiin IDL:n interaktiivista käyttöä, mutta tämä on hyvin kömpelöä monimutkaisempia asioita tehtäessä. IDL:llä on mahdollista tehdä ns. proseduuri-tiedostoja,

Lisätiedot

13 Operaattoreiden ylimäärittelyjä

13 Operaattoreiden ylimäärittelyjä 248 13 C++-kielessä voidaan operaattoreita ylimäärittää. Ylimääriteltävää operaattoria voidaan pitää ikäänkuin metodina, joka esitellään luokan esittelyssä ja määritellään luokan ulkopuolella kuten metoditkin.

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 7. huhtikuuta 2017 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille. Kirjoittamasi luokat, funktiot ja aliohjelmat

Lisätiedot

4. Luokan testaus ja käyttö olion kautta 4.1

4. Luokan testaus ja käyttö olion kautta 4.1 4. Luokan testaus ja käyttö olion kautta 4.1 Olion luominen luokasta Java-kielessä olio määritellään joko luokan edustajaksi tai taulukoksi. Olio on joukko keskusmuistissa olevia tietoja. Oliota käsitellään

Lisätiedot

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4) 2. Lisää Java-ohjelmoinnin alkeita Muuttuja ja viittausmuuttuja Vakio ja literaalivakio Sijoituslause Syötteen lukeminen ja Scanner-luokka 1 Muuttuja ja viittausmuuttuja (1/4) Edellä mainittiin, että String-tietotyyppi

Lisätiedot

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen Chapel TIE-20306 Ryhmä 91 Joonas Eloranta Lari Valtonen Johdanto Chapel on Amerikkalaisen Cray Inc. yrityksen kehittämä avoimen lähdekoodin ohjelmointikieli. Chapel on rinnakkainen ohjelmointikieli, joka

Lisätiedot

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit Liite E - Esimerkkiprojekti E Esimerkkiprojekti Olet lukenut koko kirjan. Olet sulattanut kaiken tekstin, Nyt on aika soveltaa oppimiasi uusia asioita pienen, mutta täydellisesti muotoiltuun, projektiin.

Lisätiedot

Sisällys. 12. Javan toistorakenteet. Yleistä. Laskurimuuttujat

Sisällys. 12. Javan toistorakenteet. Yleistä. Laskurimuuttujat Sisällys 12. Javan toistorakenteet Ylstä toistorakentsta. Laskurimuuttujat. While-, do-while- ja for-lauseet. Laskuri- ja lippumuuttujat. Tyypillisiä ohjelmointivirhtä. Silmukan rajat asetettu kierroksen

Lisätiedot

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1 15. Ohjelmoinnin tekniikkaa 15.1 Sisällys For-each-rakenne. Geneerinen ohjelmointi. Lueteltu tyyppi enum. 15.2 For-each-rakenne For-rakenteen variaatio taulukoiden ja muiden kokoelmien silmukoimiseen:

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 12. huhtikuuta 2019 Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä. Yksi A4-kokoinen lunttilappu

Lisätiedot

Ohjelmointi funktioiden avulla

Ohjelmointi funktioiden avulla Ohjelmointi funktioiden avulla 8 Ohjelmointi funktioiden avulla Ohjelman jakaminen hallittaviin osiin on idea, joka on perustana kaikille ohjelmointikielille. Funktio on kaikkien C++-ohjelmien perusosa.

Lisätiedot

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op) ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 22. huhtikuuta 2016 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille! Kirjoittamasi luokat, funktiot ja aliohjelmat

Lisätiedot

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma. 2. Taulukot 2.1 Sisältö Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko operaation parametrina. Taulukko ja HelloWorld-ohjelma. Taulukko paluuarvona. 2.2 Yleistä

Lisätiedot

Valinnat ja päätökset

Valinnat ja päätökset Valinnat ja päätökset 4 Valinnat ja päätökset Päätöksenteko on erittäin tärkeässä asemassa kaikissa ohjelmointikielissä. Jos ohjelman lauseiden suoritusjärjestystä ei voitaisi muuttaa tietojen vertailun

Lisätiedot

Javan perusteita. Janne Käki

Javan perusteita. Janne Käki Javan perusteita Janne Käki 20.9.2006 Muutama perusasia Tietokone tekee juuri (ja vain) sen, mitä käsketään. Tietokone ymmärtää vain syntaksia (sanojen kirjoitusasua), ei semantiikkaa (sanojen merkitystä).

Lisätiedot

1. Mitä tehdään ensiksi?

1. Mitä tehdään ensiksi? 1. Mitä tehdään ensiksi? Antti Jussi i Lakanen Ohjelmointi 1, kevät 2010/ Jyväskylän yliopisto a) Etsitään Googlesta valmis algoritmi b) Mietitään miten itse tehtäisiin sama homma kynällä ja paperilla

Lisätiedot

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU Ohjelmointi 2 Jussi Pohjolainen TAMK» Tieto- ja viestintäteknologia Tietotyypeistä C++ - kielessä useita tietotyyppejä Kirjaimet: char, wchar_t Kokonaisluvut: short, int, long Liukuluvut: float, double

Lisätiedot

Ohjelmointi 1 Taulukot ja merkkijonot

Ohjelmointi 1 Taulukot ja merkkijonot Ohjelmointi 1 Taulukot ja merkkijonot Jussi Pohjolainen TAMK Tieto- ja viestintäteknologia Johdanto taulukkoon Jos ohjelmassa käytössä ainoastaan perinteisiä (yksinkertaisia) muuttujia, ohjelmien teko

Lisätiedot

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan. Osoittimet Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan. Muistilohkon koko riippuu muuttujan tyypistä, eli kuinka suuria arvoja muuttujan

Lisätiedot

Java-kielen perusteet

Java-kielen perusteet Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, literaalivakio, nimetty vakio Tiedon merkkipohjainen tulostaminen 1 Tunnus Java tunnus Java-kirjain Java-numero

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 1.3.2010 T-106.1208 Ohjelmoinnin perusteet Y 1.3.2010 1 / 36 Monikko Monikko (engl. tuple) muistuttaa listaa, mutta monikon sisältöä ei voi muuttaa sen jälkeen,

Lisätiedot

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin. 2. Ohjausrakenteet Ohjausrakenteiden avulla ohjataan ohjelman suoritusta. peräkkäisyys valinta toisto Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet

Lisätiedot

12. Näppäimistöltä lukeminen 12.1

12. Näppäimistöltä lukeminen 12.1 12. Näppäimistöltä lukeminen 12.1 Sisällys Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä. In-luokka. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit.

Lisätiedot

Poikkeusten käsittely

Poikkeusten käsittely 11 Poikkeusten käsittely Poikkeusten käsittely on mekanismi, joka mahdollistaa kahden erillään kehitetyn ohjelmankomponentin kommunikoida keskenään, kun ohjelman suorituksen aikana kohdataan epänormaali

Lisätiedot

Taulukot. Jukka Harju, Jukka Juslin 2006 1

Taulukot. Jukka Harju, Jukka Juslin 2006 1 Taulukot Jukka Harju, Jukka Juslin 2006 1 Taulukot Taulukot ovat olioita, jotka auttavat organisoimaan suuria määriä tietoa. Käsittelylistalla on: Taulukon tekeminen ja käyttö Rajojen tarkastus ja kapasiteetti

Lisätiedot

Java kahdessa tunnissa. Jyry Suvilehto

Java kahdessa tunnissa. Jyry Suvilehto Java kahdessa tunnissa Jyry Suvilehto Ohjelma Ohjelmointiasioita alkeista nippelitietoon n. 45 min Tauko 10 min Oliot, luokat ja muut kummajaiset n. 45 min Kysykää Sisältöä ei oikeasti ole 2x45 min täytteeksi,

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2011 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2011 1 / 39 Kertausta: tiedoston avaaminen Kun ohjelma haluaa lukea tai kirjoittaa tekstitiedostoon, on ohjelmalle

Lisätiedot

Olio-ohjelmoinnissa luokat voidaan järjestää siten, että ne pystyvät jakamaan yhteisiä tietoja ja aliohjelmia.

Olio-ohjelmoinnissa luokat voidaan järjestää siten, että ne pystyvät jakamaan yhteisiä tietoja ja aliohjelmia. 4. Periytyminen 4.1. Johdantoa Käytännössä vähänkään laajemmissa ohjelmissa joudutaan laatimaan useita luokkia, joiden pitäisi pystyä välittämään tietoa toisilleen. Ohjelmien ylläpidon kannalta olisi lisäksi

Lisätiedot

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1 Ohjelmoinnin peruskurssi Y1 CSE-A1111 21.9.2015 CSE-A1111 Ohjelmoinnin peruskurssi Y1 21.9.2015 1 / 25 Mahdollisuus antaa luentopalautetta Goblinissa vasemmassa reunassa olevassa valikossa on valinta Luentopalaute.

Lisätiedot

Sisältö. 22. Taulukot. Yleistä. Yleistä

Sisältö. 22. Taulukot. Yleistä. Yleistä Sisältö 22. Taulukot Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko metodin parametrina. Taulukko ja HelloWorld-ohjelma. Taulukko paluuarvona. 22.1 22.2 Yleistä

Lisätiedot

14. Hyvä ohjelmointitapa 14.1

14. Hyvä ohjelmointitapa 14.1 14. Hyvä ohjelmointitapa 14.1 Yleistä Ohjelman elinkaari ei tyypillisesti pääty sen toteuttamiseen; ohjelmaa voidaan käyttää ja ylläpitää jopa vuosikymmeniä. Jotta koodin muuttaminen on mahdollista, sen

Lisätiedot

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana Muilla kielillä: English Suomi Pong-peli, vaihe 3 Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana Jaetaan ohjelma pienempiin palasiin (aliohjelmiin) Lisätään peliin maila (jota ei voi vielä

Lisätiedot

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python Ohjelmoinnin perusteet Y Python T-106.1208 1.4.2009 T-106.1208 Ohjelmoinnin perusteet Y 1.4.2009 1 / 56 Tentti Ensimmäinen tenttimahdollisuus on pe 8.5. klo 13:00 17:00 päärakennuksessa. Tämän jälkeen

Lisätiedot

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä Sisälls 7. Oliot ja viitteet Olio Java-kielessä. Olion luominen, elinikä ja tuhoutuminen.. Viitteiden vertailu. Varautuminen null-arvoon. Viite metodin paluuarvona.. Muuttumattomat ja muuttuvat merkkijonot.

Lisätiedot

Osoittimet. Mikä on osoitin?

Osoittimet. Mikä on osoitin? Osoittimet 7 Osoittimet On aika siirtyä käsittelemään osoittimia, C++:lle elintärkeätä ominaisuutta. Osoittimet ovat tärkeitä, koska ne luovat perustan muistin dynaamiselle varaukselle ja käytölle. Ne

Lisätiedot

7. Oliot ja viitteet 7.1

7. Oliot ja viitteet 7.1 7. Oliot ja viitteet 7.1 Sisällys Olio Java-kielessä. Olion luominen, elinikä ja tuhoutuminen. Viitteiden sijoitus. Viitteiden vertailu. Varautuminen null-arvoon. Viite metodin paluuarvona. Viite metodin

Lisätiedot

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti C! Perusteet 19.1.2017 Palautteesta (1. kierros toistaiseksi) (Erittäin) helppoa Miksi vain puolet pisteistä? Vaikeinta oli ohjelmointiympäristön asennus ja käyttö Ei selvää että main funktion pitikin

Lisätiedot

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2 6. Metodit 6.1 Sisällys Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2 Oliot viestivät metodeja kutsuen Olio-ohjelmoinnissa ohjelma

Lisätiedot

Tutoriaaliläsnäoloista

Tutoriaaliläsnäoloista Tutoriaaliläsnäoloista Tutoriaaliläsnäolokierroksella voi nyt täyttää anomuksen läsnäolon merkitsemisestä Esim. tagi ei toiminut, korvavaltimon leikkaus, yms. Hyväksyn näitä omaa harkintaa käyttäen Tarkoitus

Lisätiedot

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti: 1 (7) Tiedon lukeminen näppäimistöltä Scanner-luokan avulla Miten ohjelma saa käyttöönsä käyttäjän kirjoittamaa tekstiä? Järjestelmässä on olemassa ns. syöttöpuskuri näppäimistöä varten. Syöttöpuskuri

Lisätiedot

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti C! Perusteet 19.1.2017 Palautteesta (1. kierros toistaiseksi) Toistaiseksi helppoa Miksi vain puolet pisteistä? Vaikeinta oli ohjelmointiympäristön asennus ja käyttö Vaikeaa eroavuudet Pythonin ja C:n

Lisätiedot

Olio-ohjelmointi Syntaksikokoelma

Olio-ohjelmointi Syntaksikokoelma C++-kielen uusia ominaisuuksia Olio-ohjelmointi Syntaksikokoelma 31.10.2008 Bool-tietotyyppi: Totuusarvo true (1), jos ehto on tosi ja false (0) jos ehto epätosi. Dynaaminen muistinvaraus: Yhden muuttuja

Lisätiedot

C++11 lambdat: [](){} Matti Rintala

C++11 lambdat: [](){} Matti Rintala C++11 lambdat: [](){} Matti Rintala bool(*)(int) Tarve Tarve välittää kirjastolle/funktiolle toiminnallisuutta Callback-funktiot Virhekäsittely Käyttöliittymät Geneeristen kirjastojen räätälöinti STL:n

Lisätiedot