sami jantunen lty/tietotekniikan osasto

87
Olio-ohjelmoinnin perusteet luento 2: Johdanto C++ kieleen, Ensimmäinen C++ ohjelma, Olioiden elinkaari Sami Jantunen LTY/Tietotekniikan osasto

Upload: janina

Post on 22-Jan-2016

35 views

Category:

Documents


0 download

DESCRIPTION

Olio-ohjelmoinnin perusteet luento 2: Johdanto C++ kieleen, Ensimmäinen C++ ohjelma, Olioiden elinkaari. Sami Jantunen LTY/Tietotekniikan osasto. Sisältö. Johdanto C++ kieleen Taustatietoa C++ kielestä Johdanto C++ kielen syntaksiin Ensimmäinen C++ ohjelma Olioiden elinkaari - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Sami Jantunen LTY/Tietotekniikan osasto

Olio-ohjelmoinnin perusteetluento 2: Johdanto C++ kieleen, Ensimmäinen C++ ohjelma, Olioiden elinkaari

Sami JantunenLTY/Tietotekniikan osasto

Page 2: Sami Jantunen LTY/Tietotekniikan osasto

Sisältö Johdanto C++ kieleen

Taustatietoa C++ kielestä Johdanto C++ kielen syntaksiin Ensimmäinen C++ ohjelma

Olioiden elinkaari Olioiden syntymä Olioiden kuolema Olioiden elinkaaren määräytyminen

Page 3: Sami Jantunen LTY/Tietotekniikan osasto

C++ Varsinkin teollisuudessa yleistynyt oliokieli C-kielestä lähinnä laajentamalla johdettu Suurin osa ANSI C -ohjelmista laillisia C++-ohjelmia Tuloskoodi usein varsin tehokasta Luokkakäsite & olio-ajattelu ->korkean tason

abstraktio Mahdollisuus myös matalan tason ohjelmointiin Helpohko oppia C:tä osaaville Helppo yhdistää C-kirjastoja C++:aan Kieli ei rajoita ohjelman toteutustapaa Staattinen (käännösaikainen) tyypitys ISO C++ -standardi tarjoaa työkaluja C:n puutteiden

kiertämiseen

Page 4: Sami Jantunen LTY/Tietotekniikan osasto

C++ haittoja C:stä periytyvä turvattomuus Yhteensopivuus C:n kanssa ->ikäviä kompromisseja

oliopiirteissä Vaatii myös C-tuntemusta Runsaasti ansoja ohjelmoijalle Helppo kirjoittaa C++:aa C-mäisesti Kielessä ei kaikkialla pakollisia automaattisia

virhetarkastuksia->ohjelmien sekoamiset yleisiä C:n matalatasoisuus paistaa kielestä läpi myös

oliotasolla Periytymismekanismia käytettäessä sallii

toteutukset, jotka itse asiassa olioajattelun vastaisia Ei pakota olioajatteluun

Page 5: Sami Jantunen LTY/Tietotekniikan osasto

C++ kielen ominaisuuksia perustana on C-kieli, johon on tehty joitakin lisäyksiä ja

olio-ohjelmointimekanismit sisältävät laajennus C-kielen laajennukset:

Kommentit Tyyppimuunnokset (type casting) Syöttö ja tulostus Muuttujien näkyvyys Nimiavaruudet (namespace) Aliohjelman esittely (function prototypes) Vakiomuuttujat (constant variables) Viittausmuuttujat (reference variables) Dynaaminen muistinvaraus Inline aliohjelmat Merkkijonojen käsittely

Page 6: Sami Jantunen LTY/Tietotekniikan osasto

Ihan ensimmäinen C++ ohjelmaOhjelman runko

#include <iostream.h>

void main ( )

{

// Muistappa tämä.

// Tällainen pitää aina olla!

}

// Tämä pitäisi muuten tallettaa

//johonkin .cpp tiedostoon

Page 7: Sami Jantunen LTY/Tietotekniikan osasto

Ohjelman dokumentointi

Ohjelman dokumentointia sanotaan “kommentoinniksi”. Kääntäjä jättää kommentit huomioimatta

C++:ssa kaksi tapaa kommentoida!// Kommentoi loppurivin/* Näin kommentoidaan isompia lohkoja. Kommentointi loppuu kun vastaan tulee */

Page 8: Sami Jantunen LTY/Tietotekniikan osasto

Tyyliopas kommentoinnista Kunkin lähdekooditiedoston alkuun olisi hyvä

kommentoida seuraavat asiat: Ohjelman nimi Tiedoston nimi Tekijän nimi Kuvaus tiedoston siältämistä asioista Kehitysympäristö Muutoshistoria

Kunkin funktion alkuun tulisi kommentoida seuraavat asiat Funktion nimi Kuvaus funktiosta Funktioon tuleva tieto Funktiosta lähtevä tieto

Älä kommentoi itsestäänselvyyksiä. Perussääntö: Kerro miksi ei miten

Page 9: Sami Jantunen LTY/Tietotekniikan osasto

Esimerkki tiedoston otsikosta

/******************************************* Ohjelma: Hello World** Tiedosto: hello.CPP** Tekijä: Sami Jantunen** Kuvaus: Tulostaa näytölle sanat “Hello world” ** Ympäristö: Turbo C++ versio4, Windows 2000** Muutokset: 1.00 01.01.2004 (SJ) Ensimmäinen versio** 1.00 14.01.2004 (SJ) Laitettu iso kirjan World sanaan*************************************************/

Page 10: Sami Jantunen LTY/Tietotekniikan osasto

Esimerkki funktion otsikosta

/************************************************** CircleArea --** This function calculates the area of a circle** with the specified radius.** Inputs: the circle's radius as a parameter** Output: the circle's area as the return value**************************************************/

Page 11: Sami Jantunen LTY/Tietotekniikan osasto

Näytölle tulostus Käytä cout –oliota. Tarvitsee iostream luokkakirjastoa cout pystyy tulostamaan kutakuinkin mitä vaan.

Erityyppisiä muuttujia Useita asioita kerrallaan erikoismerkkejä kuten ‘\n’ (newline), ‘\a’ (alert), jne..

Useita asioita tulostetaan erottelemalla ne <<:llä endl:n avulla tehdään rivinsiirto Esimerkki:

#include <iostream>int main(void){string teksti = “Mitä häh?”;cout<<”Teksti: “<<endl<<teksti<<endl;return 0;

}

Page 12: Sami Jantunen LTY/Tietotekniikan osasto

Käyttäjän syötteen lukeminen Käytä cin –oliota. Tarvitsee iostream luokkakirjastoa Lue syötteet muuttujiin >> avulla Esimerkki:

#include <iostream>int main(void){// Luodaan muuttuja

int myInt;

// Luetaan tietoa näppikseltäcin >> myInt;

// Ja tulostetaan näytölle cout << “myInt is “ << myInt << endl;

return 0;}

Page 13: Sami Jantunen LTY/Tietotekniikan osasto

Sääntöjä luokkien luomisesta Luokat yleensä nimetään alkamaan isolla kirjaimella

Tidosto, jonne kirjoitat luokan pitäisi nimetä saman nimiseksi luokan kansa: <class name>.cpp

Esimerkki: Jos meillä on tarve luoda koirasta luokka annamme sille nimen Dog ja tallennamme sen tiedostoon Dog.cpp

Muista että C++ on case-sensitiivinen!

Page 14: Sami Jantunen LTY/Tietotekniikan osasto

Nimeämiskäytännöistä Nimeämiskäytännöillä on huomattava

vaikutus luokkien käytettävyyteen. Tavoite: Luokat, funktiot ja muuttujat

tulisi nimetä niin, että koodi muistuttaa englanninkielistä tekstiä

Kullakin yrityksellä tyypillisesti omat tyylioppaat.

Esimerkki tyylioppaasta: Ellemtelin tyyliopas: http://www.doc.ic.ac.uk/lab/cplus/c++.rules/

Page 15: Sami Jantunen LTY/Tietotekniikan osasto

Yksinkertaisin luokkaLuokan määre:class <class name> {};

Esimerkki: sinua pyydetään luomaan luokka X

ratkaisu:class X {};

Muista, että luokka pitäisi talletta X.cpp nimiseen tiedostoon (EI x.cpp!)

Page 16: Sami Jantunen LTY/Tietotekniikan osasto

Ensimmäinen oliopohjainen ohjelma:Koirat eläintarhassa

luokka CDog: Attribuutit (ominaisuudet) vesikauhuinen vai ei (bool) paino (int or float) nimi (string)

Toiminnallisuus murise syö

CDog

bool rabidOrNotint weightstring name

void growl()void eat()

Haluamme määritellä koiraluokan ja luoda sen mukaisia koiraolioita eläintarhaan!

Page 17: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 1: Luokan runko

class CDog {

// attribuutit tähän – nimi,

// paino, vesikauhuisuus

// toiminto tähän– murise, syö

};

CDog

bool rabidOrNotint weightstring name

void growl()void eat()

Page 18: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 2: Attribuutit(puhumme public-määreestä myöhemmin)

class CDog {

public:

bool rabidOrNot;

int weight;

string name;

// Toiminnallisuus tänne

};

CDog

bool rabidOrNotint weightstring name

void growl()void eat()

Page 19: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 3: Rakentaja (Constructor)

Rakentaja on erityinen funktioSitä käytetään alustamaan uusi olioAktivoidaan kun joku luo uuden (esim. komento new) instanssin luokastasta

Ei noudata funktion standardi puumerkkiä

Rakentajan TÄYTYY olla saman niminen kuin luokkakin

Page 20: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 3: Rakentajan suunnittelu Rakentajat eroavat toisistaan tarpeen mukaan Kysy itseltäsi:

Syntyvätkö kaikki CDog:t joko vesikauhuisena tai terveenä?(kyllä – kaikki koirat syntyvät terveinä)

Syntyvätkö kaikki CDog:t saman painoisena? (ei – koiranpennut on eripainoisia)

Onko kaikilla koiranpennuilla sama nimi? (ei – niillä on eri nimiä)

Jos vastaus kysymykseen on ei, silloin joudut toimittamaan kyseisen tiedon rakentajalle parametrinä

Page 21: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 3: Rakentajaclass CDog {public:bool rabidOrNot;int weight;char name [255];// ConstructorCDog::CDog (int x, String y) {

rabidOrNot = false;weight = x;strcpy (name, y);

}// Toiminnallisuus tänne

};

Huomaa, että jokainenCDog minkä luomme syntyy terveenä. Paino ja nimi riippuu parametrien arvoista.

Page 22: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 4: Rentoudu ja pidä tauko

Palaamme murinaan ja syömiseen hieman myöhemmin

Meidän pitää vielä puhua:LukijametodeistaMuuttajametodeistaToimintaa toteuttavista metodeista

Leikitään ensin vähän aikaan ohjelman pääalgoritmilla

Page 23: Sami Jantunen LTY/Tietotekniikan osasto

ZooNyt puhutaan ihan uudesta tiedostosta! (Zoo.cpp)

Zoo sisältää pääfunktion mainmain sisältää kontrolloivan algoritminAskeleet:

Luo runkoLuo muutamia olioita luokistaAla kertomaan mitä olioiden pitäisi tehdä

Page 24: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 1: Luo runko

#include <iostream.h>

void main ( ) {

// Luo oliosi täällä!

}

Page 25: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 2: Määritä CDog osoitin

#include <iostream.h>

void main ( ) {

CDog *c1;

}

// null means “dead”

null

c1

Page 26: Sami Jantunen LTY/Tietotekniikan osasto

new operaattori

newTuo oliot henkiin Kutsuu luokan rakentajaa (constructor)Varaa riittävästi muistia luotavalle oliolle

Formaatti:<class> *<var_name>;<var_name> = new <class> (<parameters>);

Page 27: Sami Jantunen LTY/Tietotekniikan osasto

Vaihe 3: herätä c1 henkiin

#include <iostream.h>

void main ( ) {

CDog *c1;

c1 = new CDog (14, “Bob”);}

new kutsuu CDog:n rakentajaa

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

null

c1

Page 28: Sami Jantunen LTY/Tietotekniikan osasto

Tee muistiin tilaa

null

c1

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);}

new kutsuu CDog:n rakentajaa

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

Page 29: Sami Jantunen LTY/Tietotekniikan osasto

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);

}

Tiedon välitystä

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

null

c1// Tämä tapahtuu CDog.cpp -tiedostossa

Page 30: Sami Jantunen LTY/Tietotekniikan osasto

Tiedon välitystä

null

c1

rabid:false

weight:14

name:”bob”

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);

}

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

// Tämä tapahtuu CDog.cpp -tiedostossa

Page 31: Sami Jantunen LTY/Tietotekniikan osasto

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);

CDog c2 (7, “Ethel”);

}

Luo toinen CDog olio

null

c1

rabid:false

weight:14

name:”bob”

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

// Tämä tapahtuu CDog.cpp -tiedostossa

Page 32: Sami Jantunen LTY/Tietotekniikan osasto

Tee muistiin tilaa

null

c1

rabid:false

weight:14

name:”bob”

c2

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);

CDog c2 (7, “Ethel”);

}

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

// Tämä tapahtuu CDog.cpp -tiedostossa

Page 33: Sami Jantunen LTY/Tietotekniikan osasto

Tiedon välitystä

null

c1

rabid:false

weight:14

name:”bob”

c2

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);

CDog c2 (7, “Ethel”);

}

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

// Tämä tapahtuu CDog.cpp -tiedostossa

Page 34: Sami Jantunen LTY/Tietotekniikan osasto

Kopioi arvon muistiin

null

c1

rabid:false

weight:14

name:”bob”

c2rabid:false

weight:7

name:”Ethel”

CDog::CDog (int x, char y[ ]) {

rabidOrNot = false;

weight = x;

strcpy (name, y);

}

// Tämä tapahtuu CDog.cpp -tiedostossa

#include <iostream.h>

void main ( ) {

CDog* c1;

c1 = new CDog (14, “Bob”);

CDog c2 (7, “Ethel”);

}

Page 35: Sami Jantunen LTY/Tietotekniikan osasto

Takaisin CDog-luokan pariin

class CDog {public:bool rabidOrNot;int weight;char name [255];// ConstructorCDog::CDog (int x, char y[ ]) {

rabidOrNot = false;weight = x;strcpy (name, y);

}// Toiminnallisuus. Vielä pitäisi syödä ja murista

};

CDog

bool rabidOrNotint weightstring name

void growl()void eat()

Page 36: Sami Jantunen LTY/Tietotekniikan osasto

Toiminnallisuuden toteuttaminen

void CDog::eat ( ) {

cout << name << “ is now eating” << endl;

weight++;

}

void CDog::growl ( ) {

cout << “Grrrr” << endl;

}

CDog

bool rabidOrNotint weightstring name

void growl()void eat()

Page 37: Sami Jantunen LTY/Tietotekniikan osasto

Lisää metodit luokkaanclass CDog {public:bool rabidOrNot;int weight;char name [255];// ConstructorCDog::CDog (int x, char y[ ]) {

rabidOrNot = false;weight = x;strcpy (name, y);

}void CDog::eat ( ) {

cout << name << “ is now eating” << endl;weight++;

}

void CDog::growl ( ) {cout << “Grrrr” << endl;

}};

CDog

bool rabidOrNotint weightstring name

void growl()void eat()

Page 38: Sami Jantunen LTY/Tietotekniikan osasto

“.” ja “->” operaattorit

“.” ja “->” operaattoreita käytetään jotta: päästään käsiksi olion attribuutteihin päästään käsiksi olion metodeihin päästään ylipäätänsä olion sisuksiin käsiksi

“.” operaattoria käytetään konkreetiisten instanssien kanssa (ei siis pointtereissa)Formaatti:<instanssi>.<attribuutti tai metodi>

“->” operaattoria käytetään pointtereiden kanssaFormaatti:<instanssi> -> <attribuutti tai metodi>

Page 39: Sami Jantunen LTY/Tietotekniikan osasto

“.” ja “->” operaattiorien käyttö

#include <iostream.h>void main ( ) {

CDog* c1;c1 = new CDog (14, “Bob”);CDog c2 (7, “Ethel”);c2.bark( );c1->growl( );

}

Page 40: Sami Jantunen LTY/Tietotekniikan osasto

Lukijametodit (accessors) ja muuttajametodit (modifiers) Lukijametodit

palauttaa olion atribuutin arvon ei voi olla paluuarvotyypiltään void metodissa pitää olla return komento

Muuttajametodit muuttavat olion attribuutin arvoa yleensä paluuarvotyyppinä void

Yleensä attribuutille on yksi lukijametodi ja yksi muuttajametodi (Get-Set metodit)

Page 41: Sami Jantunen LTY/Tietotekniikan osasto

Lukija- ja muuttajametoditLukijametodi rabid attribuutillebool CDog::getRabid ( ) {return rabid;}

Muuttajametodi rabid attribuutillevoid CDog::setRabid (bool myBoolean) {rabid = myBoolean;}

Sijoita nämä CDog luokan sisälle

Page 42: Sami Jantunen LTY/Tietotekniikan osasto

Lukija- ja muuttajametodien käyttö#include <iostream.h>void main ( ) {

CDog* c1;c1 = new CDog (14, “Bob”);CDog c2 (7, “Ethel”);c1->setRabid (1);// prints 1 for truecout << c1->getRabid( ) << endl;

}

Page 43: Sami Jantunen LTY/Tietotekniikan osasto

Valmista?Käännetään CDog.cpp

Ei onnistunut! Mikä meni pieleen?

Page 44: Sami Jantunen LTY/Tietotekniikan osasto

Korjataan CDog Käännetään uudestaan…

Page 45: Sami Jantunen LTY/Tietotekniikan osasto

Valmista?Käännetään seuraavaksi Zoo.cpp

Pahoja ongelmia Missä vika????

Page 46: Sami Jantunen LTY/Tietotekniikan osasto

Ongelman etsiminen….

Jotta ymmärtäisimme ongelman, tutkitaanpa ensin hieman miten C++ kääntäjät toimivat

Page 47: Sami Jantunen LTY/Tietotekniikan osasto

Käännetty vs. Tulkittu Tulkit tulkitsevat lähdekoodia “lennosta” ohjelmaa ajettaessa

Kääntäjät muuntavat lähdekoodin koneen ymmärtämään muotoon ennen ohjelman ajoa

Nopeus? Käännetty ohjelma voittaa

Turvallisuus, suoja viruksilta ym? Tulkittu ohjelma voittaa

Page 48: Sami Jantunen LTY/Tietotekniikan osasto

Ohjelman kääntäminen

Käytät jompaa kumpaa seuraavista:Komentorivi: g++ (Unixissa) IDE (Esim. Visual C++)

Page 49: Sami Jantunen LTY/Tietotekniikan osasto

Työkaluista:Integrated Development Environments (IDE)

Helppo hallita suurempienkin ohjelmien kehitystä

Siisäänrakennettu kääntäjä ja linkkeri

Usein mukana online syntaksi oppaat

Paljon käyttäjäystävällisempi kuin komentorivi

Visual C++ on esimerkki IDE:stä

Page 50: Sami Jantunen LTY/Tietotekniikan osasto

Käännösprosessi (Compiling)

Muuntaa lähdekoodin luettavasta muodosta (.cpp) tietokoneen ymmärtämään muotoon (.obj)

Yhdistää (Link) käännetyn koodin liittämiisi kirjastoihin

Tuloksena ajettava tiedosto (.exe)

Page 51: Sami Jantunen LTY/Tietotekniikan osasto

Käännös

Page 52: Sami Jantunen LTY/Tietotekniikan osasto

Hyvä tietää C++ käännösprosessista

C++ kääntäjä käsittelee kutakin lähdekooditiedostoa kerrallaan yhtenä kokonaisuutena.Jos käännettävä tiedosto sisältää viittauksia

luokkiin, mitkä on kuvattu jossain toisessa tiedostossa, ne pitäisi jollain lailla “esitellä” käännöksen aikana

Ratkaistaan ongelma eriyttämällä luokan esittely ja konkreettinen toteutus ei tiedostoihin

Page 53: Sami Jantunen LTY/Tietotekniikan osasto

Otsikkotiedostot (Header files)

Sisältävät luokan esittelyn Tiedoston nimi on muotoa

LuokanNimi.h Otsikkotiedostoon voi kirjoittaa

avoimien (public) funktioiden toteutuksia. Tätä kannattaa käyttää hyväksi yksinkertaisten get-set metodien yhteydessä

Page 54: Sami Jantunen LTY/Tietotekniikan osasto

Otsikkotiedostot (Header files) Otsikkotiedostot otetaan käyttöön seuraavilla tavoilla:

#include “MinunLuokka.h” #include <iostream.h>

#-symboli kertoo, että komento on tarkoitettu esikäsittelijän suoritettavaksi. (esikäsittely tapahtuu ennen varsinaista käännöstä)

#include –komento kertoo, että kääntäjä käsittelee käännettävää tiedostoa aivan kun #include rivin tilalla olisi kyseisen tiedoston koko sisältö

Hakasulut (<>) kertovat, että otsikkotiedosto sijaitsee kääntäjän omissa hakemistoissa

Lainausmerkit kertovat, että kyseessä on ohjelmoijan tarjoama otsikkotiedosto

Page 55: Sami Jantunen LTY/Tietotekniikan osasto

C++ ohjelman rakenne

Page 56: Sami Jantunen LTY/Tietotekniikan osasto

Kumpi tuli ensin: Muna vai kana?

MunaKana *äiti

KanaMuna *lapsi

Ongelmia luokkien esittelyssä kun luokat viittaavat toisiinsa (mutual recursion)

Viittaus toiseen luokkaan voidaan hyväksyä luokan jäsenmuuttujaksi vain jos kääntäjä on jo tietoinen luokasta.

Ratkaisuna ongelmaan on etukäteen julkaisu (forward declaration):

Page 57: Sami Jantunen LTY/Tietotekniikan osasto

Moninkertainen otsikkotiedoston esittely

Suurissa ohjelmissa #include-rakenteet tulevat mutkikkaiksi ja monitasoisiksi.

Kääntäjä voi tällöin virheellisesti saada käsittelyyn saman otsikkotiedoston useaan kertaan. Virhetilanne

tietokanta.h

#include “paivays.h”

loki.h

#include “paivays.h”

paivays.h

Pääohjelma

#include “tietokanta.h”#include “loki.h”

Page 58: Sami Jantunen LTY/Tietotekniikan osasto

Esikäääntäjän ehdollinen kääntäminen

#ifndef C_MODUULI_H

#define C_MODUULI_H

typedef struct paivays data {

int p , k , v ;

}paivays_PVM;

paivays_PVM paivays_luo( int paiva, int kuukausi, int vuosi );

paivays_tulosta( paivays_PVM kohde );

#endif /* C_MODUULI_H */

Ehdollisella kääntämisellä (#ifndef X #define X … #endif) voidaan varmistaa, että esittely näkyy kääntäjälle vain yhden kerran

Page 59: Sami Jantunen LTY/Tietotekniikan osasto

#include käytöstä vielä Vältä otsikkotiedostojen sisällyttämistä

muihin otsikkotiedostoihin Ihanteellisessa tilanteessa

otsikkotiedostoon pitää sisällyttää vain kyseisen luokan kantaluokan otsikkotiedosto

Muita pakollisia sisällytettäviä tiedostoja ovat niiden luokkien otsikkotiedostot, jonka tyyppisiä jäsenmuuttujia luokassa on

Jos vain viitataan toisen tyyppiseen olioon pelkkä luokan esittely riittää

Page 60: Sami Jantunen LTY/Tietotekniikan osasto

Linkkaus

Page 61: Sami Jantunen LTY/Tietotekniikan osasto

Milloin kannattaisi kääntää?Nyrkkisääntö: Mitä epävarmempi olet, sitä useammin käännätTämä nopeuttaa virheiden paikallistamisessa

Käännä:Ohjelman rungon luomisen jälkeen Joka 5-10 uuden rivin jälkeen

Älä kuitenkaan tule riippuvaiseksi kääntäjästä!

Page 62: Sami Jantunen LTY/Tietotekniikan osasto

Palataanpa takaisin koirat eläintarhassa esimerkkiin

Luodaan erillinen otsikkotiedosto CDog luokalle

Tiedoston nimi CDog.h Vielä paljon kerrottavaa

Ei vielä ihan tyylipuhdas luokan esittely.

class CDog {public:

int weight;bool rabid;char name [ ];CDog (int x, char y[ ]);bool getRabid ( );void setRabid (bool x);char [ ] getName ( );void setName (char z[ ]);int getWeight ( );void setWeight (int x);void bark( );void growl( );

};

CDogbool rabidOrNot

int weight

string name

void growl()void eat()

Page 63: Sami Jantunen LTY/Tietotekniikan osasto

Meidän lopullinen CDog.cpp

#include <iostream.h>

#include <CDog.h>

// Constructor

CDog::CDog (int x, char y[ ]) {

rabid = false;

weight = x;

strcpy(name, y);

}

void CDog::eat ( ) {

cout << name << “ is eating”;

}

void CDog::growl ( ) {

cout << “Grrrr”;

}

bool CDog::getRabid ( ) { return rabid;}void CDog::setRabid (bool x) { rabid = x;}int CDog::getWeight ( ) { return weight;}void CDog::setWeight (int y) { weight = y;}char[ ] CDog::getName ( ) { return name;}void setName (char z[ ]) { name = z;}

Page 64: Sami Jantunen LTY/Tietotekniikan osasto

Joko nyt? Oikeastaan ei.

Kalvon koodissa oli pieniä kirjoitusvirheitä . Löydätkö virheitä aiemmista kalvoista?

Ohessa korjauksen jälkeen onnistunut käännös

Page 65: Sami Jantunen LTY/Tietotekniikan osasto

Ensimmäinen C++ ohjelmaYhteenveto Luokkia luodessa

1. Luo luokan runko2. Määrittele attribuutit3. Kirjoita luokalle rakentaja4. Kirjoita toiminnallisuus (mukaanlukien lukija-

muuttajametodit) Kirjoita luokat eri tiedostoihin Olioiden ominaisuuksia käytetään “.”

and “->” operaattorien avulla

Page 66: Sami Jantunen LTY/Tietotekniikan osasto

Missä mennään? Johdanto C++ kieleen

Taustatietoa C++ kielestä Johdanto C++ kielen syntaksiin Ensimmäinen C++ ohjelma

Olioiden elinkaari Olioiden syntymä Olioiden kuolema Olioiden elinkaaren määräytyminen

Page 67: Sami Jantunen LTY/Tietotekniikan osasto

Olioiden syntymä Olioiden luomiseen saattaa liittyä

monimutkaisiakin toimenpiteitä kuten esim: Muistin varaaminen toisten olioiden luominen rekisteröitymiset (palvelinolio rekisteröi syntyessään

palvelunsa järjestelmänlaajuiseen tietokantaan) resurssien käyttöönotto (tietokantaolio avaa

syntyessään tietokannan sisältävän tiedoston ja lukeen sen muistiin)

muut toimenpiteet (ikkunaolio piirtää syntyessään ikkunan ruudulle)

Alustustoimenpiteet sysätään kunkin olion omalle vastuulle

Page 68: Sami Jantunen LTY/Tietotekniikan osasto

Olioiden kuolema Kun oliota ei tarvita enää, tulisi

suorittaa siivoustoimenpiteitä kuten: muistin vapautus toisten olioiden tuhuaminen rekistereistä poistuminen resurssien vapauttaminen

Siivoustoimenpiteet ovan myöskin kunkin olion omalla vastuulla

Page 69: Sami Jantunen LTY/Tietotekniikan osasto

Olioiden elinkaaren määräytyminen

Staattinen elinkaari Dynaaminen elinkaari

Page 70: Sami Jantunen LTY/Tietotekniikan osasto

Staattinen elinkaari Oliot, jotka luodaan tavallisen muuttujan tapaan.

Esim: CDog c2(7, “Ethel”);

Kissa minunKissa; Olion syntymä- ja tuhoutumishetki on määrätty jo

käännösaikana. Kääntäjä osaa suorittaa automaattisesti luomis- ja

tuhoamistoimenpiteet Suositeltava tapa. Ei vaaraa muistivuodoista. Silti mahdollisuus vakaviin virheisiin .

Esimerkki: Osoittimet saattavat viitata automaattisesti tuhottavaan olioon

Muista, että olio tuhoutuu automaattisesti tietyssä kohdassa ohjelmaa

Page 71: Sami Jantunen LTY/Tietotekniikan osasto

Dynaaminen elinkaari Olion elinkaaresta huolehtiminen on

jätetty ohjelmoijan vastuulle Olio ei tuhoudu automaattisesti. Se

täytyy erikseen tuhota. Pakko käyttää tilanteissa, missä olion

elinkaari ei rajaudu tiettyyn osaa koodia Mitä luot new -komennolla, sen tuhoat delete –komennolla

Vaarallista! Muistivuotoja tulee helposti

Page 72: Sami Jantunen LTY/Tietotekniikan osasto

Tyypillisiä dynaamiseen luontiin liittyviä ongelmia

Unohdetaan tuhota olio(t) Olio tuhotaan kahteen kertaan Tuhotun olion käyttäminen Taulukkojen tuhoaminen

Page 73: Sami Jantunen LTY/Tietotekniikan osasto

Esimerkki(asetetaan d1 osoittamaan d2:n osoittamaan olioon)

Dog *d1, *d2;d1 = new Dog (5, “bob”);d2 = new Dog (5, “bob”);

d1 = d2;

null

d1 d2

rabid=false

weight=5

name=“bob”

rabid=false

weight=5

name=“bob”

Page 74: Sami Jantunen LTY/Tietotekniikan osasto

Muistin tarkastelu

Nyt, d1 ja d2 osoittavat samaan olioon

Mutta mikään ei osoita tähän

Koska mikään osoitin ei osoitaa kyseiseen olioon, emme voi enää käyttää sitä.

Kutsumme tätä osaa muistiaroskaksi. Teimme oliosta käyttökelvottoman!

null

d1 d2

rabid=false

weight=5

name=“bob”

rabid=false

weight=5

name=“bob”

Page 75: Sami Jantunen LTY/Tietotekniikan osasto

Muistin vapauttamisesta

Muista vapauttaa käyttämätön muistialue

Sääntö: Älä koskaan vain aseta osoitinta null:ksi

Muista käyttää delete ( ) operaattoria

Esim: delete d1;

Page 76: Sami Jantunen LTY/Tietotekniikan osasto

Ohjeita virheiden välttämiseen Määrittele, kuka “omistaa” olion ja on täten

vastuussa sen tuhoamisesta Pyri siihen, että dynaamisesti luotuja olioita ei

käytetä monen eri tahon toimesta. Nollaa osoittimet tuhoamisen jälkeen

Paivays *p = new Paivays;//käytetään päiväystädelete p; p =0;

Tämä estää tilanteen, missä muuttujat viittaavaat muistipaikkaan, missä tuhotun olion ylitse ei ole kirjoitettu vielä uutta tietoa (Zombie-olioiden käyttö)

Kirjoita koodia, mikä pyrkii toipumaan virhetilanteista (Tästä lisää myöhemmissä luennoissa)

Page 77: Sami Jantunen LTY/Tietotekniikan osasto

Rakentaja (constructor) Tunnetaan myös nimellä Muodostaja Tehtävänä hoitaa kaikki uuden olion

alustamiseen liittyvät toimenpiteet Jäsenmuuttujien alustus Olioon kuuluvien olioiden ulkopuolisten

tietorakenteiden ja olioiden luominen Olion rekisteröiminen jonnekkin

Kolmenlaisia rakentajia: oletusrakentaja (default constructor)

olion tietojäsenten alustus oletusarvoilla kopiointirakentaja (copy constructor)

olion tietojäsenten alustus toisesta oliosta kopioimalla parametrilliset rakentajat

Page 78: Sami Jantunen LTY/Tietotekniikan osasto

Rakentaja (constructor) Sääntöjä Kääntäjä luo jokaiselle luokalle

oletusrakentajan ellei sellaista ole itse ohjelmoitu

Rakentajan nimi täytyy olla sama kuin luokan nimi

Rakentaja ei palauta paluuarvoa Rakentajalle ei voi määritellä

paluuarvon tyyppiä (ei edes void)

Page 79: Sami Jantunen LTY/Tietotekniikan osasto

Oletusrakentaja (default constructor) Esimerkki

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;

}

Page 80: Sami Jantunen LTY/Tietotekniikan osasto

Rakentaja (constructor) Sijoitus vs. Alustuslista

Pvm::Pvm(const int p_pp, const int p_kk, const int p_vv): pp(p_pp), kk(p_kk), vv(p_vv){//Ei mitään tehtävää täällä

}

Pvm::Pvm(const int p_pp, const int p_kk, const int p_vv){

pp = p_pp;kk = p_kk;vv = p_vv;

}

Jäsenmuuttujiin sijoitus

Alustuslistan käyttö

Page 81: Sami Jantunen LTY/Tietotekniikan osasto

Rakentaja (constructor) Sijoitus vs. Alustuslista Useinmiten sijoituksen ja alustuslistan käytöllä ei ole

lopputuloksessa eroa Vakioita ja viittauksia ei kuitenkaan voi alustaa

sijoittamalla. Alustuslistaa käyttämällä tämän voi tehdä. Esimerkki:

class ConstRef {public:

ConstRef( int ii);private:

int i;const int ci;int &ri;

};

ConstRef:: ConstRef (int ii ){ // sijoitus i=ii //OK ci=ii //error: ei voi sijoittaa vakioon ri=i; //error: ri ei ole alustettu}

Alustuslistaa käyttäen:ConstRef:: ConstRef (int ii )

:ci(ii),ri(i) //alustus{ i=ii;}

Sijoitusta yrittäen:Luokan kuvaus:

Page 82: Sami Jantunen LTY/Tietotekniikan osasto

Kopiorakentaja (copy constructor) Saa parametrina viitteen olemassa

olevaan saman luokan olioon. Tehtävänä luoda identtinen kopio

parametrina saadusta oliosta Kääntäjä kutsuu sitä automaattisesti

tilanteissa, missä kopion luominen on tarpeen.

Jos kopiorakentaja puuttuu, se luodaan kääntäjän toimesta automaattisesti

Asiasta puhutaan lisää myöhemmillä luennoilla

Page 83: Sami Jantunen LTY/Tietotekniikan osasto

Parametrillinen rakentaja Tarjoaa luokan luojalle mahdollisuuden

määritellä kullekkin luotavalle oliolle alustettavat arvot

Parametrillinen rakentaja on aina ohjelmoijan kirjoittama

Samat säännöt kuin oletusrakentajalla. Poikkeus: Parametrillisen rakentajan parametreihin voidaan

määritellä tarvittaessa myös oletusarvot (näistäkin lisää myöhemmissä luennoissa)

Luokka voi sisältää useita erilaisilla parametreilla varustettuja rakentajia

Kääntäjä ei generoi oletusrakentajaa, jos ohjelmoija on määritellyt luokkaan parametrillisen rakentajan

Page 84: Sami Jantunen LTY/Tietotekniikan osasto

Parametrillinen rakentajaEsimerkki

#include <iostream>#include <time>class Pvm{

int pp, kk, vv;public:

Pvm(const int, const int, const int); //parametrillinen rakentaja

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;

}

Page 85: Sami Jantunen LTY/Tietotekniikan osasto

Purkaja Tunnetaan myös nimellä Hajoitin Purkajan nimi on ~Luokan_nimi Purkaja ei saa parametreja Purkajalla ei ole tyyppiä, ei saa palauttaa

mitään arvoa Esittelyssä ei saa esiintyä varattuja sanoja

const, volatile tai static Purkaja voi olla (suositellaan!!) virtuaalinen

(liittyy periytymiseen, tästä puhutaan lisää myöhemmin)

Page 86: Sami Jantunen LTY/Tietotekniikan osasto

Purkaja Purkajaa kutsutaan automaattisesti seuraavissa tilanteissa:

Poistutaan koodialueesta, missä olio on luotu staatisella tavalla Tuhotaan olio delete -komennolla

On mahdollista (mutta hyvin harvinaista) kutsua purkajaa eksplisiittisesti. Purkajan kutsu:

Olio.Luokka:: ~Luokka();Olio->Luokka:: ~Luokka();

Purkajan esittely:class Luokka...public:

~Luokka();};

Purkajan määrittely:Luokka:: ~Luokka(){

tietojäsenten tyhjennys}

Page 87: Sami Jantunen LTY/Tietotekniikan osasto

Purkaja esimerkki#include <iostream.h>#include <time.h>class Pvm{

int pp, kk, vv;public:

Pvm(const int, const int);Pvm(const Pvm &, const int = 96);Pvm &Pvm::operator=(const Pvm &);~Pvm();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;}Pvm &Pvm::operator=(const Pvm &p_pvm){

pp = p_pvm.pp;kk = p_pvm.kk;vv = p_pvm.vv;return (*this);

}

Pvm::~Pvm(){

pp = 0;kk = 0;vv = 0;

}void Pvm::nayta() const{

cout<<pp<<'/'<<kk<<'/'<<vv;}int main(void){

cout<<"Päivä1: ";Pvm Paiva1(1, 2);Paiva1.Pvm::~Pvm();Paiva1.nayta();

cout<<"\nPäivä2: ";Pvm *Paiva2 = new Pvm(2, 2);Paiva2->Pvm::~Pvm();Paiva2->nayta();delete Paiva2;return 0;

}