Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Monimuotoinen luokka tMyn1 Monimuotoinen luokka Monimuotoinen luokka mahdollistaa saman jäsenfunktion toteutuksen monella tavalla. Tällöin puhutaan virtuaalisesta.

Samankaltaiset esitykset


Esitys aiheesta: "Monimuotoinen luokka tMyn1 Monimuotoinen luokka Monimuotoinen luokka mahdollistaa saman jäsenfunktion toteutuksen monella tavalla. Tällöin puhutaan virtuaalisesta."— Esityksen transkriptio:

1 Monimuotoinen luokka tMyn1 Monimuotoinen luokka Monimuotoinen luokka mahdollistaa saman jäsenfunktion toteutuksen monella tavalla. Tällöin puhutaan virtuaalisesta jäsenfunktiosta. Monimuotoinen luokka sisältää virtuaalisen jäsenfunktion oletustoteutuksen. Monimuotoinen kantaluokka periytetään johdettuun luokkaan public-periytymistavalla. Tällöin johdettu luokka perii kaikki tavalliset jäsenfunktiot ja virtuaalisten jäsenfunktioiden oletustoteutukset.

2 Monimuotoinen luokka tMyn2 Virtuaalisten jäsenfunktioiden oletustoteutukset on mahdollista korvata (override) johdetussa luokassa. Monimuotoisuus tarkoittaa eri olioiden kykyä vastata samaan viestiin eri tuloksella. Monimuotoisuutta hyväksi käyttämällä olion käyttäytymistavan määrää olion määrittelyluokkaan toteutettu jäsenfunktio. Kääntäjä ei voi päätellä olion määrittelyluokkaa, koska ohjelmassa esitelty oliotunnus voi viitata eri aikoina eri olioihin. Nämä oliot voi olla määritelty eri luokkiin. Siispä monimuotoisuuteen liittyy aina osoitinmuuttuja olioon tai viittaus olioon.

3 Monimuotoinen luokka tMyn3 Overriding When a virtual function definition is changed in a derived class, then the function definition is said to be overridden. A distinction is sometimes made between the terms redefined and overridden. Both terms refer to changing the definition of the function in a derived class. If the function is a virtual function, it is called overriding. If the function is not a virtual function, it is called redefining.

4 Monimuotoinen luokka tMyn4 Järjestelmän on sidottava määrittelyluokka olion tunnukseen ja pääteltävä suoritettava jäsenfunktio ohjelman suorituksen aikana. Ajon aikana tapahtuvaa sidontaa kutsutaan dynaamiseksi sidonnaksi. Monimuotoinen kantaluokka mahdollistaa jäsenfunktion kutsun tulkitsemisen monella eri tavalla. Monimuotoisesti tulkittavaksi haluttava jäsenfunktio on määriteltävä monimuotoisessa luokassa virtuaaliseksi.

5 Monimuotoinen luokka tMyn5 Virtuaalisella jäsenfunktiolla voi olla useita toteutusratkaisuja ja kutsua vastaavan toteutusratkaisun järjestelmä etsii olion määrittelyluokasta ohjelman suorituksen aikana. Luokka on monimuotoinen, jos se sisältää yhdenkin virtuaalisen jäsenfunktion. Monimuotoisella kantaluokalla on kahdenlaisia jäsenfunktioita: tavallisia ja virtuaalisia.

6 Monimuotoinen luokka tMyn6 Tavallinen jäsenfunktio –tarkoitettu ajettavaksi aina, kun monimuotoisen luokan tai siitä johdetun luokan olio saa jäsenfunktion nimeä vastaavan viestin. –Jos kantaluokan jäsenfunktiota ei ole merkitty virtuaaliseksi, mutta sen toimintaa muutetaan johdetussa luokassa (=redefinition), niin silloin sidonta tapahtuu käännösaikana. –staattinen sidonta olion tunnuksen esittelyluokan perusteella.

7 Monimuotoinen luokka tMyn7 Virtuaalinen jäsenfunktio –tarkoitettu ajettavaksi monimuotoisen luokan oliolle ja kantaluokasta johdetun luokan oliolle sellaisessa tapauksessa missä tämän johdetun luokan olion määrittelyluokassa ei ole virtuaalisen jäsenfunktion korvaavaa toteutusta. Siis jokaisessa johdetussa luokassa ei ole välttämättä korvattua (override) toteutusta kantaluokan virtuaalisesta jäsenfunktiosta! –voidaan korvata johdetussa luokassa (override). –dynaaminen sidonta olion määrittelyluokan perusteella.

8 Monimuotoinen luokka tMyn8 Tehdään aluksi esimerkki, jossa kaikki ei suju halutulla tavalla. Toteutetaan kantaluokkaan kaksi jäsenfunktiota, joista toinen kaiuttaa näytölle tilavuuden, void HaeTilavuus(), ja toinen laskee sen, double LaskeTilavuus(). Johdettuun luokkaan toteutetaan myös jäsenfunktio double LaskeTilavuus(), ja sen toimintaa muutetaan (redefinition!). Main-osassa luodaan olio sekä kanta- että johdettuun luokkaan (oliot eka ja toka, vastaavasti). Sitten halutaan kaiuttaa kummankin olion tilavuudet näytölle. Mikä menee vikaan?

9 Monimuotoinen luokka tMyn9 The difference between overriding and redefinition. Both terms refer to changing the definition of the function in a derived class. If the function is a virtual function, it’s called overriding. If the function is not a virtual function, it’s called redefining.

10 Monimuotoinen luokka tMyn10 // Laatikko.h #ifndef LAATIKKO_H #define LAATIKKO_H class Laatikko { public: Laatikko(); void AsetaLeveys(); void AsetaSyvyys(); void AsetaKorkeus(); Laatikko(double, double, double); void AsetaLeveys(double); void AsetaSyvyys(double); void AsetaKorkeus(double); void HaeTilavuus(); double LaskeTilavuus();

11 Monimuotoinen luokka tMyn11 protected: double m_leveys; double m_syvyys; double m_korkeus; }; #endif

12 Monimuotoinen luokka tMyn12 // Pahvilaatikko.h #ifndef PAHVILAATIKKO_H #define PAHVILAATIKKO_H #include "Laatikko.h" class Pahvilaatikko: public Laatikko { public: Pahvilaatikko(); void AsetaPaino(); Pahvilaatikko(double); void AsetaPaino(double); Pahvilaatikko(double, double, double, double); double LaskeTilavuus(); private: double m_paino; }; #endif

13 Monimuotoinen luokka tMyn13 // Laatikko.cpp #include "stdafx.h" #include #include "Laatikko.h" using namespace System; using namespace std; Laatikko::Laatikko() { cout<<"Kantaluokan oletusmuodostin, olio "<<this<<endl; AsetaLeveys(); AsetaSyvyys(); AsetaKorkeus(); }

14 Monimuotoinen luokka tMyn14 void Laatikko::AsetaLeveys() { cout<<"Anna leveys: "; cin>>m_leveys; cin.get(); } void Laatikko::AsetaSyvyys() { cout<<"Anna syvyys: "; cin>>m_syvyys; cin.get(); } void Laatikko::AsetaKorkeus() { cout<<"Anna korkeus: "; cin>>m_korkeus; cin.get(); }

15 Monimuotoinen luokka tMyn15 Laatikko::Laatikko(double leveys, double syvyys, double korkeus) { cout<<"Kantaluokan 3 param. muodostin, olio "<<this<<endl; AsetaLeveys(leveys); AsetaSyvyys(syvyys); AsetaKorkeus(korkeus); } void Laatikko::AsetaLeveys(double leveys) { m_leveys=leveys; } void Laatikko::AsetaSyvyys(double syvyys) { m_syvyys=syvyys; }

16 Monimuotoinen luokka tMyn16 void Laatikko::AsetaKorkeus(double korkeus) { m_korkeus=korkeus; } void Laatikko::HaeTilavuus() { cout<<"Tilavuus on "<<LaskeTilavuus()<<endl; } double Laatikko::LaskeTilavuus() { return m_leveys*m_syvyys*m_korkeus; }

17 Monimuotoinen luokka tMyn17 // Pahvilaatikko.cpp #include "stdafx.h" #include #include "Pahvilaatikko.h" using namespace System; using namespace std; Pahvilaatikko::Pahvilaatikko() :Laatikko() { cout<<"Johdetun luokan oletusmuodostin, olio "<<this<<endl; AsetaPaino(); }

18 Monimuotoinen luokka tMyn18 void Pahvilaatikko::AsetaPaino() { cout<<"Anna paino: "; cin>>m_paino; cin.get(); } Pahvilaatikko::Pahvilaatikko(double paino) :Laatikko() { cout<<"Johdetun luokan 1 param. muodostin, olio ” <<this<<endl; AsetaPaino(paino); } void Pahvilaatikko::AsetaPaino(double paino) { m_paino=paino; }

19 Monimuotoinen luokka tMyn19 Pahvilaatikko::Pahvilaatikko(double leveys, double syvyys, double korkeus, double paino) :Laatikko(leveys, syvyys, korkeus) { cout<<"Johdetun luokan 4 param. muodostin, olio "<<this<<endl; AsetaPaino(paino); } double Pahvilaatikko::LaskeTilavuus() { return 0.85*m_leveys*m_syvyys*m_korkeus; }

20 Monimuotoinen luokka tMyn20 // moniEi1Main.cpp : main project file. #include "stdafx.h" #include #include "Pahvilaatikko.h" using namespace System; using namespace std; int main(array ^args) { Laatikko eka=Laatikko(1.1, 2.2, 3.3); Pahvilaatikko toka=Pahvilaatikko(1.1, 2.2, 3.3, 68.9); eka.HaeTilavuus(); toka.HaeTilavuus(); return 0; }

21 Monimuotoinen luokka tMyn21

22 Monimuotoinen luokka tMyn22 Tavoitteena oli, että käytettäisiin kantaluokasta periytettyä jäsenfunktiota void HaeTilavuus() kutsumaan tarvittaessa joko kantaluokan jäsenfunktiota double LaskeTilavuus() tai sitten samannimistä johdetun luokan jäsenfunktiota. Ongelmana on, että jäsenfunktio void HaeTilavuus() on esitelty kantaluokkaan. Niinpä se kutsuu aina samaisen luokan jäsenfunktiota double LaskeTilavuus(). Tätä kutsutaan staattiseksi sidonnaksi (static resolution, static binding, early binding). Ohjelman käännösvaihe määrää sen minkä luokan jäsenfunktiota funktio void HaeTilavuus() kutsuu.

23 Monimuotoinen luokka tMyn23 Voitaisiinko ohjelma saada toimimaan vanhoilla konsteilla? Kokeillaan seuraavaa: kutsutaan suoraan johdetun luokan jäsenfunktiota double LaskeTilavuus(). Toisena kokeiluna käytetään osoitinmuuttujaa, joka on kantaluokan osoitinmuuttuja. Annetaan sille johdetun luokan olion osoite:

24 Monimuotoinen luokka tMyn24 //sama kuin edellisessä esimerkissä … int main(array ^args) { Laatikko eka=Laatikko(1.1, 2.2, 3.3); Pahvilaatikko toka=Pahvilaatikko(1.1, 2.2, 3.3, 68.9); eka.HaeTilavuus(); cout<<"Olion toka tilavuus on " <<toka.LaskeTilavuus()<<endl; Laatikko* osoitin=&toka; cout<<"Olion toka tilavuus on nyt " LaskeTilavuus()<<endl; return 0; }

25 Monimuotoinen luokka tMyn25

26 Monimuotoinen luokka tMyn26 Huomataan, että ensimmäinen muutos toimii juuri niin kuin halutaankin. Johdetun luokan olio toka kutsuu saman luokan jäsenfunktiota LaskeTilavuus() – näinhän se pitääkin olla. Sitä vastoin jälkimmäinen vaihtoehto toimii vastoin toiveitamme (toki kääntäjän mielestä kaikki on hyvin), vaikka osoitinmuuttujalla ’osoitin’ on olion toka osoite! Kummassakin tapauksessa siis sidonta tapahtuu staattisesti, käännösaikaisesti.

27 Monimuotoinen luokka tMyn27 Kun kutsutaan staattisesti jäsenfunktiota (=käännösaikaisesti) osoitinmuuttujan avulla, niin se, mistä luokasta jäsenfunktio kutsutaan, määräytyy yksin osoitinmuuttujan tyypin perusteella eikä sen perusteella mitä oliota osoitinmuuttuja osoittaa (=minkä luokan osoite osoitinmuuttujan sisältönä sattuisi olemaan). Edellinen esimerkki toimi siis kääntäjän kannalta seuraavasti:

28 Monimuotoinen luokka tMyn28 int main(array ^args) { Laatikko eka=Laatikko(1.1, 2.2, 3.3); Pahvilaatikko toka=Pahvilaatikko(1.1, 2.2, 3.3, 68.9); cout<<"Olion toka tilavuus on " <<toka.Pahvilaatikko::LaskeTilavuus()<<endl; Laatikko* osoitin=&toka; cout<<"Olion toka tilavuus on nyt " Laatikko::LaskeTilavuus()<<endl; return 0; }

29 Monimuotoinen luokka tMyn29 Yhteenveto staattisesta sidonnasta: Järjestelmä suorittaa tavallisen jäsenfunktion aina kutsussa esiintyvän olion tunnuksen esittelyluokasta. Jos ohjelmassa käytetään hyväksi kokonaista luokkahierarkiaa ja ohjelman käsittelemät oliot on määritelty luokkahierarkian eri luokkiin, on kunkin luokan oliolle oltava sen määrittelyluokan mukaiset oliotunnukset. Automaattisen olion tunnuksen esittely on samalla sen (olion) määrittely. Siis tunnuksen esittelyn yhteydessä tapahtuu myös tarvittavan keskusmuistitilan varaaminen.

30 Monimuotoinen luokka tMyn30 Siis vaikkapa luokanNimi olionTunnus=luokanNimi(); Dynaamisen olion tunnuksen esittely ja olion määrittely voivat tapahtua yhtäaikaisesti tai eri aikaan. Dynaamisen olion tunnuksen esittely on osoitinmuuttujan esittely. Sama osoitinmuuttuja voi osoittaa eri hetkinä eri olioihin ja samaan olioon voi olla useita osoittimia yhtä aikaa. Dynaamisen olion esittely ja määrittely erikseen: luokanNimi* olionTunnus; olionTunnus=new luokanNimi();

31 Monimuotoinen luokka tMyn31 Luokkahierarkiaan perustuen johdetun luokan oliota voidaan vaihtoehtoisesti käsitellä epäsuorasti joko johdetun luokan tai kantaluokan osoitinmuuttujalla. Jos johdetun luokan oliota käsitellään kantaluokan osoitinmuuttujan avulla, niin siinä tapauksessa kääntäjä valitsee kutsuttavan jäsenfunktion (tavallinen jäsenfunktio) aina kantaluokasta. Luonnollisesti, jos johdetun luokan oliota käsitellään samaisen luokan osoitinmuuttujalla, niin silloin edellä mainittua mahdollista ongelmaa ei synny.

32 Monimuotoinen luokka tMyn32 Jos siis johdetun luokan oliota käsitellään samaisen luokan tunnuksella, sitoo kääntäjä jäsenfunktiokutsuun tässä johdetussa luokassa määritellyn jäsenfunktion, jos sieltä sellainen löytyy. Jos sitä ei löydy samasta luokasta, etsii kääntäjä jäsenfunktion toteutusta kantaluokasta.

33 Monimuotoinen luokka tMyn33 Pyöritellään tätä samaa asiaa vielä näin päin: Kun oliota käsitellään epäsuorasti osoitinmuuttujan avulla, niin kääntäjä tekee tavallisten jäsenfunktioiden sidonnan suoraan käyttämällä kutsussa käytetyn oliotunnuksen ESITTELYLUOKKAA (=osoitinmuuttujan esittely), ei olion varsinaista MÄÄRITTELYLUOKKAA (=tilanvarauksen tekeminen). Määräävänä tekijänä on siis osoitinmuuttujan ”kotiluokka”, ei se, minkä luokan oliota osoitinmuuttuja sattuu osoittamaan.


Lataa ppt "Monimuotoinen luokka tMyn1 Monimuotoinen luokka Monimuotoinen luokka mahdollistaa saman jäsenfunktion toteutuksen monella tavalla. Tällöin puhutaan virtuaalisesta."

Samankaltaiset esitykset


Iklan oleh Google