Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
KiadtaHadi Darmali Megváltozta több, mint 5 éve
1
Feladat Készítsünk programot, amely ciklikusan egy egyenest forgat 8 fokonként, mialatt 3 db vektort mozgat és forgat 5, 6 ill 7 fokonként, és kijelzi a szituációkat, amikor valamelyik vektor és az egyenes párhuzamos.
2
Objektumok számbavétele (Milyen dolgok szerepelnek a leírásban?)
Dolgok - főnevek Vektor, egyenes, szituáció Vektor -3db Különböző vektorok ugyanolyan jellegű dolgok, azaz ugyanannak a típusnak különböző példányai.˙ Szituáció nem önálló objektum vektor és egyenes között fennálló viszony, asszociáció.
3
Következtetés Fontos objektumok két típusba sorolhatók: Vector Line
4
Objektumok absztrakt definíciója
Objektumokon végezhető műveletek (egy típushoz tartozó különböző objektumokon ugyanolyan műveletek végezhetők, ezért a műveleteket típusokhoz rendeljük). Műveletek - igék Vektor : forgatás, eltolás. Egyenes: forgatás. Párhuzamosság vizsgálat (Vektor, v. egyenes?)
5
Objektumok belső szerkezete
Objektumok belső tulajdonságának megállapítása a leírásból nem lehetséges Korábbi ismeretekre kell támaszkodnunk! (Ez a tipikus!) Két dimenziós vektor: x és y koordináta. Egyenes: egy pontjának és irányvektorának két-két koordinátája.
6
Elemzés eredménye Objektum Típus Attribútumok Felelősség
vektor(ok) Vector x, y vektor forgatása, eltolása, párhuzamosság? egyenes Line x0,y0,vx,vy egyenes forgatása,
7
Implementáció C++-ban
Az osztály olyan általánosított struktúra, amely egységbe zárja az adatokat és a műveleteket és alapértelmezésben minden tagja- függetlenül attól, hogy adatról, vagy függvényről van-e szó - az osztályon kívülről elérhetetlen.
8
Egységbe zárás C++-ban értelmezése
class Vector { //private: double x, y; //adatok, állapot public: void Set (double x, double y ) ; void Translate ( Vector d ) ; void Rotate (double fi ) ;
9
Vector v; v.Set ( 3.0, 4.0); v.x = 6.0; //Fordítási hiba!
10
Tagfüggvények implementációja
deklaráció és definíció - osztályon belül definíció- osztályon kívül (deklaráció osztályon belül) class Vector { double x, y; //adatok, állapot public: void Set (double x0, double y0 ) {x = x0; y = y0;} void Rotate (double ) ; //csak deklaráció }; void Vector::Rotate (double fi) { //definíció double nx = cos(fi)*x + sin(fi)*y; //x,y saját adat double ny = -sin(fi)*x + cos(fi)*y; x = nx; y = ny ; //vagy this -> y = ny; }
11
Megjegyzések tagfüggvények számára az adattagok közvetlenül elérhetők.
Tagfüggvény osztályon kívüli definíciójakor jelezni kell, hogy melyik osztályhoz tartozik: scope(::) operátor. Pl.: Vector::Rotate() Osztályon belül definiált függvény automatikusan inline függvény lesz. Minden függvényben létezik egy nem látható paraméter a this. A this mindig az aktuális objektumra mutató pointer.
12
osztály - struktúra hasonlósága osztály adattagjai
osztály - struktúra hasonlósága osztály adattagjai -> struktúra osztály függvénymezői-> globális függvények
13
Globális függvények Pl.: Vector osztály Set függvényének a neve: Set_Vector_dbldbl . Mivel mindegyik más objektumon dolgozik 1000 db objektum példány esetén 1000 db függvény kellene. Megoldás: egy függvény, amely paraméterként megkapja az adatokat összefogó struktúra kezdőcímét, azaz az objektum saját címét.
14
Példa class Vector { double x, y; //adatok, állapot public: void Set (double x0, double y0 ) {x = x0; y = y0;} void Rotate (double ) ; //csak deklaráció struct Vector { double x, y }; void Set_Vector (struct Vector *this, double x0, double y0) { this -> x = x0; this -> y = y0; } void Rotate_Vector (Vector *this, double fi ) { ... }
15
Objektumok létrehozása
Vector osztály alapján objektumokat definiálhatunk. Az objektumokat értékadásban felhasználhatjuk Tagfüggvények segítségével üzeneteket küldhetünk nekik.
16
Konstruktor és destruktor
class Vector { double x, y; public: Vector(double x0, double y0) {x=x0; y=y0; } //konstruktornak nincs visszatérési típusa ~Vector() { } //destruktornak nincs típusa sem argumentuma
17
Objektumok létrehozása
Konstruktorral és destruktorral felszerelt Vector osztály alapján definiált objektumok használata: { Vector v1(0.0, 1.0 ); //konstruktor hívás Vector v2 = v1; v1 = Vector (3.0, 4.0 ) ; //ideiglenes objektum létrehozása és v1-hez rendelése //destruktor az ideiglenesre // 2db destruktor hívás: v1, v2
18
Konstruktor és destruktor
Alapértelmezés szerinti konstruktor - argumentumot nem vár (Ha egyáltalán nem definiálunk, akkor a fordító egy ilyet létrehoz. Objektumok élettartama- születésük, megszűnésük. Globális objektumok (argumentuma csak konstans kifejezés lehet
19
Objektumok tömbje 100 db Vector objektum:
Vector v [100]; Mivel a konstruktor argumentumai nem átadhatók, kell definiálni egy alapértelmezésű konstruktort is.
20
Objektumok dinamikus definiálása
new és delete operátorok használata Egy dinamikusan létrehozott objektum a new operátor alkalmazásakor születik meg és a delete alkalmazásakor szűnik meg. ( A konstruktor és destruktor is ekkor fut le.). Példa: Vector *pv = new Vector (1.5, 1.5); Vector *av = new Vector [100 ];
21
Dinamikus tömbök Tömb esetében a delete hatására a memória felszabadul, de csak a legelső elemre fut le a destruktor delete [ ] av; //mind a 100 elemre lefut a destruktor
22
A védelem enyhítése - a barát (friend) mechanizmus
Párhuzamosság ellenőrzése -AreParallel függvény Kérdések - Vector osztályhoz tartozzon - Line osztályhoz tartozzon - egyikhez sem tartozzon, legyen globális függvény és mindkét objektumot argumentumként kapja.
23
friend mechanizmus Probléma: AreParallel() egyik objektum adattagjaihoz sem férhet hozzá. Megoldás: engedélyezhetjük egy idegen függvény vagy egy osztály összes tagfüggvénye számára az adattagokhoz való hozzáférést. Ezt a friend kulcsszó teszi lehetővé.
24
Függvény számára a hozzáférés biztosítása
class Line { double x0, y0, vx, vy ; public: friend Bool AreParallel (Line, Vector ); }; class Vector { double x, y; public: ... friend Bool AreParallel (Line, Vector ); }; Bool AreParallel ( Line l, Vector v) { return ( l.vx * v.y == l.vy * v.x ); }
25
Osztály számára a hozzáférés biztosítása
A Line osztály a Vector osztályt fogadja barátjának: class Vector ; class Line { friend class Vector; double x0, y0, vx, vy ; public: }; class Vector { double x, y; public: ... Bool AreParallel ( Line l) { return ( l.vx * y == l.vy *x ); } }
26
Operátorok átdefiniálása (operator overloading)
Matematikai és programnyelvi operátok többrétűsége (polimorfizmusa) közismert. + számok összeadása mátrixok összeadása A fordítást az operandusok típusának megfelelően végzi el az adott nyelv fordítóprogramja. C++ -lehetővé teszi, hogy a nyelv operátorait ne csak a beépített típusokra, hanem az osztállyal gyártott objektumokra is alkalmazzuk. (Operátor overloading )
27
Műveletek vektorokkal
Jelöljük a vektorok összeadását + jellel és az értékadást az = operátorral. Vector v, v1, v2 ; v = v1 + v2 ; Mit csinál a fordító ezen sorok hatására?
28
Fordító teendői - Mindenekelőtt tudja, hogy az összeadást előbb kell elvégezni, mint az értékadást. (Műveletek precedenciája) - Megvizsgálja a műveletben résztvevő operandusok típusait. (+ jel bal és jobb oldalán álló operandusok típusát).
29
+ összeadás műveletének elvégzése
Jelen esetben mindkét operandus típusa Vector - a fordító nem rendelkezik beépített művelettel. Megnézi, hogy a baloldali objektum osztályának (Vector) van-e olyan összeadás tagfüggvénye, azaz operator+ tagfv-e, amellyel neki a jobboldali objektumot el lehet küldeni. Megnézi, hogy van-e olyan operator+ globális függvény, amely első argumentumként az első operandust, második argumentumként a másodikat várja.
30
Tagfüggvény, vagy globális függvény?
Ez azt jelenti, hogy megnézi, hogy a Vector osztálynak létezik-e - Vector::operator+(Vector) tagfüggvénye vagy (kizáró vagy) - operator+(Vector, Vector ) globális függvény
31
Műveletek vektorokkal
A v1 + v2 kifejezés az alábbi függvényhívással ekvivalens ( a változattól függően): - v1.operator+ ( v2 ); //Vector:: operator+(Vector); //tagfüggvény - operator+ ( v1, v2 ); //operator+ (Vector,Vector); //globális függvény
32
= jel operátor feldolgozása
Az egyenlőség két operandusú (ezt a fordító tudja.) A bal oldalon a v objektumot találja, amely Vector típusú. A jobb oldalon az összeadásnak megfelelő függvényhívás van. Ez olyan típust képvisel, amilyet az összeadás függvény visszaad. Ezt a visszatérési típust ugyancsak Vector-nak kell definiálni. Megvizsgálja a fordító, hogy létezik-e operator= tagfüggvénye a bal oldali objektumnak, melynek a jobb oldali objektumot elküldhetjük Vector::operator=(Vector).
33
+ művelet vektorokkal Van-e globális függvény? Néhány operátornál a globális függvény használata nem megengedett Pl.: értékadás =, index [ ], függvényhívás () indirekt mezőválasztó -> operátorok. A helyettesítés: v.operator= (v1.operator+ ( v2 ) ) ; vagy v.operator= (operator+ ( v1, v2 ) ) ; Ha a fordító nem talál megfelelő függvényt, hiszen az = operátornak van alapértelmezése, mégpedig az adatmezők bitenkénti másolása.
34
Operátor átdefiniálás tagfüggvénnyel
class Vector { double x, y ; public: Vector ( double x0, double y0 ) {x=x0; y=y0;} Vector operator+ (Vector v) ; }; Vector Vector:: operator+(Vector v) { Vector sum (v.x+x, v.y+y ) ; return sum ; };
35
Operátor+ tagfüggvény megvalósítása
Az összeadás függvény belsejében létrehoztunk egy ideiglenes objektumot, melynek attribútumait a konstruktorának segítségével a bal (üzenet célja) és a jobb (üzenet paramétere) operandusok x és y koordinátáinak az összegével inicializáltuk.Közvetlen hozzáférés a v objektum privát mezőihez: (Lehetséges?) Közvetlen elérhetőség érvényes a családtagokra is. (Minden ugyanezen osztállyal definiált objektumra).
36
Összeadás üzenetre egy rossz megoldás
Vector Vector:: operator+(Vector v) { x+ = v.x ; y+ = v.y ; return *this ; v értéke jó lesz, de v1 is elromlik!
37
Operátor-átdefiniálás globális függvénnyel
class Vector { double x, y ; public: Vector ( double x0, double y0 ) {x=x0; y=y0;} friend Vector operator+ (Vector& v1,Vector& v2) ; }; Vector operator+(Vector& v1, Vector& v2) { Vector sum (v1.x+v2.x, v1.y+v2.y ) ; return sum ; }
38
Operátor - átdefiniálás Tagfüggvénnyel vagy globális függvénnyel?
OO program működése lényegében az objektumok közötti üzenetváltásokkal valósul meg. A globális függvények nem illenek ebbe a koncepcióba. Néha nincs más megoldás!
39
Példa arra, amikor csak globális függvényt használhatunk:
Skalár vektor szorzás Vector v1, v2 (3.0, 4.0 ); v1 = 2 * v2 ; A bal oldalon most nem objektum, hanem egy beépített típus, int van, annak egy operator*(Vector) tagfüggvényt nem tudunk definiálni.
40
Operátor átdefiniálás szabályai
A C++-ban szinte minden operátor átdefiniálható, kivéve: - tagkiválasztó “.” - érvényességi kör (scope):: - a feltételes választás ( ? : ) Az átdefiniálás során figyelembe veendő szabályok: - a szintaxis nem változtatható meg - az egyoperandus·/kétoperandus· tulajdonság nem változtatható meg - a precedencia nem változtatható meg.
41
Konverziós operátorok
Az átdefiniálható operátorok külön családját képezik az ún. konverziós (cast) operátorok. Konverzió kijelölése: (céltípus) változó Értékadásban (ha két oldalon eltérő típus van) és függvényhíváskor (átadott objektum típusa a deklarációban megadottól eltér) automatikus típuskonverzió megy végbe. Implicit típuskonverzió.
42
Konverziós operátorok átdefiniálása
Példa: Két double koordinátát tartalmazó vektor objektumok és az MS_Windows-ban megszokott forma ( egy vektor egy long típusban kerül tárolásra úgy, hogy a long alsó helyiértékű 16 bitje az x, felső helyiértékű 16 bitje az y koordináta) között végzünk átalakításokat.
43
Típuskonverzió Vector vec ( 1.0, 2.5 ) ; long point = 14L + 36 L << 16 ) ; //14, 36 koordinátájú pont extern f (long) ; extern g (Vector) ; vec = (Vector ) point ; //explicit vec = point ; //implicit g (point ) ; //implicit point = (long ) vec ; //explicit point = vec ; //implicit f (vec ) ; //implicit
44
Konverziós operátorok átdefiniálása
Újdonság a C++-ban: osztállyal gyártott objektumokra is definiálhatunk átalakító operátorokat. Két eset: - osztállyal definiált típusról alakítunk át más típusra ( ami lehet más osztállyal definiált típus vagy beépített típus). - Beépített vagy osztállyal definiált típust konvertálunk osztállyal definiált típusra.
45
Konverzió osztállyal definiált típusról
A Vector -> típus (jelen esetben long) átalakítást kell megvalósítanunk, amely a Vector osztályban egy operator típus ( ) ; tagfüggvénnyel lehetséges. Ehhez a tagfüggvényhez nem lehet visszatérési típus és nem lehet argumentum sem.
46
Megvalósítás class Vector { double x, y ; public: operator long ( ) { return ((long) x + (long) y <<16 ) ; } }
47
Beépített vagy osztállyal definiált típust konvertálunk osztállyal definiált típusra
Amennyiben egy objektumot akarunk létrehozni egy más típusú változóból, olyan konstruktort kell készíteni, ami argumentumként a megadott típust fogadja el. A long -> Vector átalakításhoz tehát a Vector osztályban egy long argumentum· konstruktor szükséges:
48
Példa class Vector { double x, y ; public: Vector ( long lo) { x = lo & 0xffff; y = lo >>16 ; }
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.