Elemi Alkalmazások Fejlesztése II. Osztályok közötti kapcsolatok öröklődés asszociáció aggregáció kompozíció
1. Feladat Készítsünk programot, amellyel testek térfogatát határozhatjuk meg, illetve megadhatjuk azt is, hogy az egyes testfajtákból hány objektum létezik! A lehetséges fajták: szabályos sokszögek: gömb, kocka, tetraéder, oktaéder; hasáb jellegű testek: henger, négyzet alapú hasáb, szabályos háromszög alapú hasáb; gúla jellegű testek: kúp, négyzetes gúla.
2. A megoldás menete Az előző órán megismert megoldást módosítsuk. Hasáb jellegű testek esetén az alapterület kiszámítását egy beágyazott objektumra delegáljuk. Így elérhető, hogy négyzet alapú hasáb, illetve gúla esetén ugyanazt a műveletet használjuk fel, nem kell ugyanazt a megvalósítást elkészítenünk két különböző osztályban. Ugyanez igaz háromszög, illetve kör alap esetén is. Az alapterület kiszámítását az Alap absztrakt osztály deklarálja, amit a konkrét Kor, Negyzet, Haromszog osztályokban valósítunk meg. A beágyazott objektum ennek megfelelően az Alap osztályból származtatott konkrét osztály példánya lesz.
3. Osztálydiagram Test Gömb Szabályos Hasáb Henger Kocka Kúp Gúla Négyzetes Tetraéder NGúla Háromszöges Oktaéder
Test # méret : double - darab : int # Test(méret : double) + Test() + Térfogat() : double + Darab() : int Szabályos Hasáb - darab : int # Szabályos(méret : double) + Szabályos() + Térfogat() : double # Szorzó() : double + Darab() : int # magasság : double - darab : int # Hasáb(méret : double, magasság : double) + Hasáb() + Térfogat() : double + Darab() : int # alap Alap + Terület(m : double) : double
Alap + Terület(m : double) : double Kör + Terület(m : double) : double Négyzet + Terület(m : double) : double Háromszög + Terület(m : double) : double
Szabályos - darab : int # Szabályos(méret : double) + Szabályos() + Térfogat() : double # Szorzó() : double + Darab() : int Gömb Kocka Tetraéder Oktaéder - darab : int - szorzó : double = 4π/3 + Gömb(méret : double) + Gömb() # Szorzó() : double + Darab() : int - darab : int + Kocka(méret : double) + Kocka() # Szorzó() : double + Darab() : int - darab : int - szorzó : double = 2/12 + Tetraéder(méret : double) + Tetraéder() # Szorzó() : double + Darab() : int - darab : int - szorzó : double = 2/3 + Oktaéder(méret : double) + Oktaéder() # Szorzó() : double + Darab() : int
Hasáb # magasság : double - darab : int # Hasáb(méret : double, magasság : double) + Hasáb() + Térfogat() : double + Darab() : int Gúla - darab : int # Gúla(méret : double, magasság : double) + Gúla() + Térfogat() : double + Darab() : int
Hasáb # magasság : double - darab : int # Hasáb(méret : double, magasság : double) + Hasáb() + Térfogat() : double + Darab() : int - darab : int Henger - darab : int Négyzetes - darab : int Háromszöges + Henger(méret : double, magasság : double) + Henger() + Darab() : int + Négyzetes(méret : double, magasság : double) + Négyzetes() + Darab() : int + Háromszöges(méret : double, magasság : double) + Háromszöges() + Darab() : int
- darab : int Gúla # Gúla(méret : double, magasság : double) + Gúla() + Térfogat() : double + Darab() : int - darab : int Kúp - darab : int NGúla + Kúp(méret : double, magasság : double) + Kúp() + Darab() : int + NGúla(méret : double, magasság : double) + NGúla() + Darab() : int
4. Osztályok Nem változnak az előző megoldáshoz képest: Test, Szabalyos, Gomb, Kocka, Tetraeder, Oktaeder.
5. Az Alap osztály class Alap public: virtual double Terulet(double m) const = 0; ~Alap() protected: Alap() ;
6. A Kor osztály class Kor : public Alap public: double Terulet(double m) const return PI * m * m; ;
7. A Negyzet osztály class Negyzet : public Alap public: double Terulet(double m) const return m * m; ;
8. A Haromszog osztály class Haromszog : public Alap public: double Terulet(double m) const return SQ3 * m * m / 4.0;
9. A Hasab osztály class Hasab : public Test public: ~Hasab(); double Terfogat() const; static int Darab() return darab; protected: Hasab(double meret, double magassag); protected: double magassag; Alap *alap; private: static int darab; ;
int Hasab::darab = 0; Hasab::Hasab(double meret, double magassag) : Test(meret) this->magassag = magassag; darab++; Hasab::~Hasab() darab--; double Hasab::Terfogat() const return alap->terulet(meret) * magassag;
10. A Gula osztály class Gula : public Hasab public: ~Gula(); double Terfogat() const; static int Darab() return darab; protected: Gula(double meret, double magassag); private: static int darab; ;
int Gula::darab = 0; Gula::Gula(double meret, double magassag) : Hasab(meret, magassag) darab++; Gula::~Gula() darab--; double Gula::Terfogat() const return (alap->terulet(meret) * magassag) / 3.0;
11. A Henger osztály class Henger : public Hasab public: Henger(double meret, double magassag); ~Henger(); static int Darab() return darab; private: static int darab; ;
int Henger::darab = 0; Henger::Henger(double meret, double magassag) : Hasab(meret, magassag) darab++; alap = new Kor(); Henger::~Henger() darab--; delete alap;
12. A Negyzetes osztály class Negyzetes : public Hasab public: Negyzetes(double meret, double magassag); ~Negyzetes(); static int Darab() return darab; private: static int darab; ;
int Negyzetes::darab = 0; Negyzetes::Negyzetes(double meret, double magassag) : Hasab(meret, magassag) darab++; alap = new Negyzet(); Negyzetes::~Negyzetes() darab--; delete alap;
13. A Haromszoges osztály class Haromszoges : public Hasab public: Haromszoges(double meret, double magassag); ~Haromszoges(); static int Darab() return darab; private: static int darab; ;
int Haromszoges::darab = 0; Haromszoges::Haromszoges(double meret, double magassag) : Hasab(meret, magassag) darab++; alap = new Haromszog(); Haromszoges::~Haromszoges() darab--; delete alap;
14. A Kup osztály class Kup : public Gula public: Kup(double meret, double magassag); ~Kup(); static int Darab() return darab; private: static int darab; ;
int Kup::darab = 0; Kup::Kup(double meret, double magassag) : Gula(meret, magassag) darab++; alap = new Kor(); Kup::~Kup() darab--; delete alap;
15. A NGula osztály class NGula : public Gula public: NGula(double meret, double magassag); ~NGula(); static int Darab() return darab; private: static int darab; ;
int NGula::darab = 0; NGula::NGula(double meret, double magassag) : Gula(meret, magassag) darab++; alap = new Negyzet(); NGula::~NGula() darab--; delete alap; A főprogram értelemszerűen nem változik az előző megoldáshoz képest.
16. Javítás Vegyük észre, hogy Alap típusú elemekből elég egyetlen példányt létrehoznunk, azt közösen használhatják a megfelelő testek. Tehát elég egyetlen Kör, egytelen Négyzet és egyetlen Háromszög objektum. A közös Kör objektumot használhatja az összes kör alapú test. (Eddig minden test külön objektumot hozott létre.)
Alap + Terület(m : double) : double Kör Négyzet Háromszög - példány : Kör - példány : Négyzet - példány : Háromszög + Terület(m : double) : double + Példány() : Kör + Terület(m : double) : double + Példány() : Négyzet + Terület(m : double) : double + Példány() : Háromszög
17. A Kor osztály class Kor : public Alap public: double Terulet(double m) const return PI * m * m; static Kor *Peldany(); private: static Kor *peldany; Kor() ; Kor *Kor::peldany = 0; Kor *Kor::Peldany() if ( peldany == 0 ) return peldany; peldany = new Kor();
18. A Negyzet osztály class Negyzet : public Alap public: double Terulet(double m) const return m * m; static Negyzet *Peldany(); private: static Negyzet *peldany; Negyzet() ; Negyzet *Negyzet::peldany = 0; Negyzet *Negyzet::Peldany() if ( peldany == 0 ) peldany = new Negyzet(); return peldany;
19. A Haromszog osztály class Haromszog : public Alap public: double Terulet(double m) const return SQ3 * m * m / 4.0; static Haromszog *Peldany(); private: static Haromszog *peldany; Haromszog() ; Haromszog *Haromszog::peldany = 0; Haromszog *Haromszog::Peldany() if ( peldany == 0 ) peldany = new Haromszog(); return peldany;
Ezután az összes Hasáb jellegű osztály konstruktorában a new helyett az osztályszintű Peldany művelet szerepel. A destruktorban pedig elmarad a felszabadítás. Például a Henger osztályban: Henger::Henger(double meret, double magassag) : Hasab(meret, magassag) darab++; alap = Kor::Peldany(); Henger::~Henger() darab--;
20. Asszociáció és aggregáció implementálása Ezeket a kapcsolatokat mutatók segítségével lehet megvalósítani, ahogy a Hasáb osztály és az Alap osztály kapcsolatánál láthattuk. Ha a multiplicitás többszörös, akkor egy megfelelő méretű mutató tömböt kell felvenni. 21. Kompozíció implementálása A kompozíció attribútum jellegű kapcsolat, ezért a kompozíciós objektum beágyazott objektumként (adattag) jelenik meg az összetett objektumban. Ha egyéb, gyakorlati okokból mutató(ka)t használunk, akkor az összetett objektum létrehozásakor, a konstruktorban, létre kell hoznunk a beágyazott objektumokat is, és a mutatókat csak az objektum megszűnésekor, a destruktorban, változtathatjuk meg, szabadíthatjuk fel.
Rendszer név Bolygó név Csillag class Rendszer Rendszer(string nev, int meret, string nevek[]); ~Rendszer();... private: Csillag csillag; int bolgyoszam; Bolygo* bolygok[]; string nev; ;
class Bolygo Bolygo(string nev);... ; Rendszer::Rendszer(string nev, int meret, string nevek[]) this.nev = nev; bolygoszam = meret; // csillag automatikusan létrejön bolygok = new Bolygo *[bolygoszam]; for ( int i = 0; i < bolygoszam; i++ ) bolygok[i] = new Bolygo(nevek[i]); Rendszer::~Rendszer() delete [] bolygok;