830 likes | 1.01k Views
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
E N D
Olio-ohjelmoinnin perusteetluento 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 • Olioiden syntymä • Olioiden kuolema • Olioiden elinkaaren määräytyminen
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
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
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
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
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 */
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
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 ** ***********************************************/
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 **************************************************/
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> intmain(void) { string teksti = “Mitä häh?”; cout<<”Teksti: “<<endl<<teksti<<endl; return 0; }
Käyttäjän syötteen lukeminen • Käytä cin –oliota. • Tarvitsee iostream luokkakirjastoa • Lue syötteet muuttujiin >> avulla • Esimerkki: #include <iostream> intmain(void) { // Luodaan muuttuja int myInt; // Luetaan tietoa näppikseltä cin >> myInt; // Ja tulostetaan näytölle cout << “myInt is “ << myInt << endl; return 0; }
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!
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/
Yksinkertaisin luokka • Luokan 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!)
CDog boolrabidOrNot intweight stringname void growl() void eat() Ensimmäinen oliopohjainen ohjelma:Koirat eläintarhassa luokka CDog: • Attribuutit (ominaisuudet) • vesikauhuinen vai ei (bool) • paino (int or float) • nimi (string) • Toiminnallisuus • murise • syö Haluamme määritellä koiraluokan ja luoda sen muikaisia koiraolioita eläintarhaan!
CDog boolrabidOrNot intweight stringname void growl() void eat() Vaihe 1: Luokan runko class CDog { // attribuutit tähän – nimi, // paino, vesikauhuisuus // toiminto tähän– murise, syö };
CDog boolrabidOrNot intweight stringname void growl() void eat() Vaihe 2: Attribuutit(puhumme public-määreestä myöhemmin) class CDog { public: bool rabidOrNot; int weight; string name; // Toiminnallisuus tänne };
Vaihe 3: Rakentaja (Constructor) • Rakentaja on erityinen funktio • Sitä käytetään alustamaan uusi olio • Aktivoidaan kun joku luo uuden (esim. komento new) instanssin luokastasta • Ei noudata funktion standardi puumerkkiä • Rakentajan TÄYTYY olla saman niminen kuin luokkakin
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ä
Vaihe 3: Rakentaja class CDog { public: bool rabidOrNot; int weight; char name [255]; // Constructor CDog::CDog (int x, String y) { rabidOrNot = false; weight = x; strcpy (name, y); } // Toiminnallisuus tänne }; Huomaa, että jokainen CDog minkä luomme syntyy terveenä. Paino ja nimi riippuu parametrien arvoista.
Vaihe 4: Rentoudu ja pidä tauko • Palaamme murinaan ja syömiseen hieman myöhemmin • Meidän pitää vielä puhua: • Lukijametodeista • Muuttajametodeista • Toimintaa toteuttavista metodeista • Leikitään ensin vähän aikaan ohjelman pääalgoritmilla
Zoo • Nyt puhutaan ihan uudesta tiedostosta! (Zoo.cpp) • Zoo sisältää pääfunktion main • main sisältää kontrolloivan algoritmin • Askeleet: • Luo runko • Luo muutamia olioita luokista • Ala kertomaan mitä olioiden pitäisi tehdä
Vaihe 1: Luo runko #include <iostream.h> void main ( ) { // Luo oliosi täällä! }
Vaihe 2: Määritä CDog osoitin #include <iostream.h> void main ( ) { CDog *c1; } // null means “dead” Memory null c1
new operaattori • new • Tuo oliot henkiin • Kutsuu luokan rakentajaa (constructor) • Varaa riittävästi muistia luotavalle oliolle • Formaatti: <class> *<var_name>; <var_name> = new <class> (<parameters>);
Vaihe 3: herätä c1 henkiin #include <iostream.h> void main ( ) { CDog *c1; c1 = new CDog (14, “Bob”); } Memory null c1 • new kutsuu CDog:n rakentajaa • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • }
Tee muistiin tilaa #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); } Memory null c1 • new kutsuu CDog:n rakentajaa • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • }
Tiedon välitystä #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); } Memory null c1 • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • } // Tämä tapahtuu CDog.cpp -tiedostossa
Tiedon välitystä #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); } Memory null c1 • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • } // Tämä tapahtuu CDog.cpp -tiedostossa rabid:false weight:14 name:”bob”
Luo toinen CDog olio #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); CDog c2 (7, “Ethel”); } Memory null c1 // Tämä tapahtuu CDog.cpp -tiedostossa • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • } rabid:false weight:14 name:”bob”
Tee muistiin tilaa #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); CDog c2 (7, “Ethel”); } Memory null c1 // Tämä tapahtuu CDog.cpp -tiedostossa • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • } c2 rabid:false weight:14 name:”bob”
Tiedon välitystä #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); CDog c2 (7, “Ethel”); } Memory null c1 // Tämä tapahtuu CDog.cpp -tiedostossa • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • } c2 rabid:false weight:14 name:”bob”
Kopioi arvon muistiin #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); CDog c2 (7, “Ethel”); } Memory null c1 // Tämä tapahtuu CDog.cpp -tiedostossa • CDog::CDog (int x, char y[ ]) { • rabidOrNot = false; • weight = x; • strcpy (name, y); • } c2 rabid:false rabid:false weight:14 weight:7 name:”bob” name:”Ethel”
CDog boolrabidOrNot intweight stringname void growl() void eat() Takaisin CDog-luokan pariin class CDog { public: bool rabidOrNot; int weight; char name [255]; // Constructor CDog::CDog (int x, char y[ ]) { rabidOrNot = false; weight = x; strcpy (name, y); } // Toiminnallisuus. Vielä pitäisi syödä ja murista };
CDog boolrabidOrNot intweight stringname void growl() void eat() Toiminnallisuuden toteuttaminen void CDog::eat ( ) { cout << name << “ is now eating” << endl; weight++; } void CDog::growl ( ) { cout << “Grrrr” << endl; }
CDog boolrabidOrNot intweight stringname void growl() void eat() Lisää metodit luokkaan class CDog { public: bool rabidOrNot; int weight; char name [255]; // Constructor CDog::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; } };
“.” ja “->” operaattorit • “.” ja “->” operaattoreita käytetään jotta: • päästään käsiksi olion attribuutteihin • päästään käsiksi olion metodeihin • päästä 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>
“.” ja “->” operaattiorien käyttö #include <iostream.h> void main ( ) { CDog* c1; c1 = new CDog (14, “Bob”); CDog c2 (7, “Ethel”); c2.bark( ); c1->growl( ); }
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)
Lukija- ja muuttajametodit • Lukijametodi rabid attribuutille bool CDog::getRabid ( ) { return rabid; } • Muuttajametodi rabid attribuutille void CDog::setRabid (bool myBoolean) { rabid = myBoolean; } • Sijoita nämä CDog luokan sisälle
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 true cout << c1->getRabid( ) << endl; }
Valmista?Käännetään CDog.cpp Ei onnistunut! Mikä meni pieleen?
Valmista?Käännetään seuraavaksi Zoo.cpp • Pahoja ongelmia • Missä vika????
Ongelman etsiminen…. • Jotta ymmärtäisimme ongelman, tutkitaanpa ensin hieman miten C++ kääntäjät toimivat
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
Ohjelman kääntäminen • Käytät jompaa kumpaa seuraavista: • Komentorivi: g++ (Unixissa) • IDE (Esim. Visual C++)
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ä
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)