Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Osztály fogalom Új fogalom: osztály (class).

Hasonló előadás


Az előadások a következő témára: "Osztály fogalom Új fogalom: osztály (class)."— Előadás másolata:

1 Osztály fogalom Új fogalom: osztály (class).
Az osztály olyan általánosított struktúrának tekinthető, 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 szó - az osztályon kívülről elérhetetlen. 18

2 A Date osztály class Date { public: Date ( int mn, int dy, int yr) ;
int getMonth ( ) { return month ; } int getDay ( ) { return day ; } int getYear ( ) { return year ; } int setMonth ( int mn ); int setDay ( int dy ) ; int setYear ( int yr ) ; void display ( ) ; ~Date ( ) ; private: int month ; int day ; int year ; } ;

3 public és private kulcsszavak
Publikus (public) tagok - kívülről elérhető tagok. Privát (private) tagok - kívülről elérhetetlen tagok. Egy olyan osztály, amelynek egyetlen tagja sem elérhető, semmire sem használható. private és public kulcsszavakkal a hozzáférés szelektív engedélyezése és tiltása valósítható meg. Hatása addig tart, amíg meg nem változtatjuk újabb private vagy public kulcsszóval. 19

4 public és private kulcsszavak
Általában az adattagokat szoktuk private-tal a függvényeket public-cal definiálni. A struktúrában is használhatók ezek a kulcsszavak Struktúrában alapértelmezés a public hozzáférés a tagokhoz. 20

5 Tagfüggvények Ezeket szokás még metódusoknak illetve üzenetnek is nevezni. Eddig csupán a függvények deklarációját helyeztük el az osztály deklarációjának belsejében. A függvények törzsének a megadása során két megoldás közül választhatunk: - definiálhatjuk őket az osztályon belül (deklaráció és definíció nem válik el egymástól) - definiálhatjuk őket az osztályon kívül (deklaráció és definíció szétválik). 21

6 Megjegyzések a példával kapcsolatban
A tagfüggvényekben a privát adattagok közvetlenül elérhetők. (A C függvény hivatkozik a dt.month nevű struktúraváltozóra. A C++ tagfüggvény közvetlenül eléri a month változót. 22

7 Megjegyzések a példával kapcsolatban
Ha a tagfüggvényt osztályon kívül definiáltuk, akkor azt is egyértelműen jelezni kell, hogy melyik osztályhoz tartozik, hiszen egy Date nevű tagfüggvénye több osztálynak is lehet. Erre a célra szolgál az ún. scope operator (::), melynek segítségével a Date::display() formában a Date osztály display tagfüggvényét jelöljük ki. 23

8 Metódus osztályon kívüli definíciója
void Date::display() { static char *name [ ] = {“zero” , “January” , February” , “March” , “April” , “May” , “June” ,“July” , August” . September” , “Oktober” ,“November” , “December” } ; cout << name [ month ] << ‘.’ << day << ‘.’ << year ; }

9 Megjegyzések a példával kapcsolatban
Az osztályon belül definiált tagfüggvény automatikusan inline függvény lesz. (Áttekinthető osztálydefiníciókban úgyis csak tipikusan egysoros függvények engedhetők meg, amelyeket hatékonysági okokból makróként célszerű deklarálni. 24

10 this mutató Minden tagfüggvényben létezik egy nem látható paraméter, amelyre this elnevezéssel lehet hivatkozni. A this mindig az éppen aktuális objektumra mutató pointer. Így a saját adatmezők is elérhetők ezen keresztül, tehát az x helyett a függvényben this -> x -t is írhatnánk. 25

11 Az osztályok nyelvi megvalósítása
Az osztály működésének jobb megértése érdekében érdemes egy kicsit elgondolkodni azon, hogy hogyan valósítja meg azt a C++ fordító. C++ -ról C-re fordító programot kell írnunk (Tételezzük fel!) Vizsgáljuk meg, hogy a fogalmainkat hogyan lehet leképezni a C nyelvre! 26

12 Az osztályok nyelvi megvalósítása 1.
A C nyelvben az osztályhoz legközelebbi adattípus a struktúra. Az osztály adattagjait egy struktúrában helyezzük el. A függvénymezőket globálisként kell kezelnünk. A névütközések elkerülése végett a globális függvénynevekbe bele kell kódolni azon osztály nevét, amelyhez tartozik, sőt, ha ezen függvénynévhez különféle paraméterezésű függvények tartoznak akkor a paraméterek típusait is. Pl. display_Date ( ha paramétere lenne, pl. 3 db int, akkor display_Date_intintint. 27

13 Az osztályok nyelvi megvalósítása 2.
A különválasztás során, ha például 1000 db Date objektumunk van, akkor látszólag 1000 db display függvénynek kellene léteznie. Ha még hozzátesszük, hogy az objektumok dinamikusan keletkezhetnek és szűnhetnek meg a program futása során, akkor látható, hogy nem ez a járható út. A feladatot egyetlen display függvénnyel kell elvégezni, de hogy az tudja, hogy milyen adatokkal kell dolgoznia, meg kell kapnia annak az objektumnak a címét, amelynek az adattagjait kezeli. 28

14 Az osztályok nyelvi megvalósítása 3.
Ennek a legegyszerűbb megvalósítása az, hogy a függvény megkapja az adatstruktúra kezdőcímét első paraméterként. Minden tagfüggvény első nem látható paramétere az adattagokat összefogó struktúra címét tartalmazó mutató. Ez a mutató nem más, mint az objektum saját címe, azaz a this pointer. A this pointer alapján a lefordított program az összes objektum attribútumot indirekt módon éri el. 29

15 Fontos! Privát tagokat csak az osztály tagfüggvényei érik el (és a friend class) Példa: void main ( ) { int i ; Date myDate ( 3, 12, 1985 ) ; i = myDate.month ; // hiba myDate.day = 1 ; // hiba } 30

16 Fontos! Csak tagfüggvényeken keresztül hivatkozhatunk az adattagokra.
myDate.display ( ) //myDate adattagjait jeleníti meg; yourDate.display ( ) //yourDate adattagjait jeleníti meg; Egy tagfüggvény automatikusan használja a kurrens objektum adattagjait Egy tagfüggvényt pointeren keresztül is hívhatunk: Date myDate ( 3, 12, 1985 ); Date *datePtr = &myDate ; datePtr -> display (); 31

17 Tagfüggvények hívása referenciával
Date myDate ( 3, 12, 1985 ); Date &OtherDate = myDate ; OtherDate.display (); //myDate tartalmát jeleníti meg 32

18 Konstruktor A Date osztály alapján objektumokat (változókat) definiálhatunk, melyeket a szokásos módon értékadásban felhasználhatunk, illetve tagfüggvényeik segítségével üzeneteket küldhetünk nekik. A C++ osztályok rendelkezhetnek egy olyan speciális tagfüggvénnyel, amely akkor kerül meghívásra, amikor egy objektumot létrehozunk. Ezt a tagfüggvényt konstruktornak nevezzük. A konstruktor neve mindig megegyezik az osztály nevével. 33

19 Konstruktor A Date osztály konstruktora a Date() függvény!
Egy osztálynak több konstruktora is lehet. Ha egy osztálynak nincs konstruktora, akkor a fordító egy paraméter nélküli változatot automatikusan létrehoz. Ha viszont bármilyen bemenetű konstruktort megadunk, akkor automatikus konstruktor nem jön létre. Az argumentumot nem váró konstruktort alapértelmezés szerinti konstruktornak nevezzük. Az alapértelmezés szerinti konstruktort feltételező objektumdefiníció során a konstruktor üres () zárójeleit nem kell kiírnunk. 34

20 Objektumdefiníció Date myDate( 3, 12, 1985) ; Date myDate ;
Bármikor egy objektumot definiálunk, akkor a konstruktor végrehajtásra kerül. 35

21 Globális objektumok Globális objektumok a program betöltése alatt, azaz a main() meghívása előtt születnek meg, így konstruktoruk is a main() hívása előtt aktivizálódik. Ezekben az esetekben a konstruktor argumentuma csak konstans kifejezés lehet, és nem szabad olyan dolgokra támaszkodnunk, amelyet a main() inicializál. 36

22 Objektumok tömbje Date d [100];
Ebben az esetben nem tudunk argumentumokat átadni, ezért tömb csak olyan típusú objektumokból hozható létre, amelyek alapértelmezésű konstruktorokat tartalmaznak. 37

23 Objektumok definiálása
Az objektumokat definiálhatjuk dinamikusan is, azaz memóriafoglalással (allokáció), a new és a delete operátorok segítségével. Természetesen egy dinamikusan létrehozott objektum a new operátor alkalmazásakor születik meg és a delete operátor alkalmazásakor vagy a program végén szűnik meg, így a konstruktor és a destruktor függvények hívása is a new és a delete operátorhoz kapcsolódik. A new operátorral történő memóriafoglalásnál a kért objektum típusa után meg kell adni a konstruktor argumentumait is: Date *pd = new Date ( 3, 12, 1985 ) ; Date *pdt = new Date [100] ; 38

24 A delete operátor A delete operátor egy objektumra értelemszerűen használható (delete pd, de tömbök esetében a delete pdt hatására felszabadítás ugyan megtörténik, de csak az első objektumra hívja meg a destruktort. Ha feltétlenül mind a 100 elemre meg akarjuk hívni a destruktort, akkor így kell használni: delete [ ] pdt ; 39

25 Destruktor Ha egy objektum érvényességi tartománya megszűnik, akkor meghívásra kerül a destruktor függvény. Szerepe: egy objektum megszüntetése Igazán akkor lényeges, ha az objektumok dinamikus memóriát használnak. A destruktor neve megegyezik az osztály nevével, csak előtte ~ (tilde) jel legyen. A destruktornak nincs paramétere nem lehet visszatérési értéke nem átdefiniálható. 40

26 A konstruktor is overload-olható
class Date { public: Date ( ) ; //Konstruktor paraméterek nélkül Date ( int mn, int dy, int yr) ; int getMonth ( ) { return month ; } int getDay ( ) { return day ; } int getYear ( ) { return year ; } int setMonth ( int mn ); int setDay ( int dy ) ; int setYear ( int yr ) ; void display ( ) ; ~Date ( ) ; private: int month ; int day ; int year ; } ; Date::Date ( ) month = day = year = 1 ; //Inicializálja az adattagokat. }

27 Demo program a konstruktorok és destruktorok futásával kapcsolatban
#include <iostream.h> #include <string.h> class Demo //Demo osztály definíciója { public: Demo (const *nm ); ~Demo ( ) ; private: char name [ 20 ] ; } ;

28 // Demo konstruktora Demo::Demo ( const char *nm ) {
strncpy ( name, nm, 20 ) ; cout << “Constructor called for “ << name << ‘\n’ ; } //Demo destruktora Demo::~Demo ( ) cout << “Destructor called for “ << name << ‘\n’ ;

29 Egy függvény egy lokális és egy statikus lokális objektum definiálásával
void func ( ) { Demo localFuncObject (“localFuncObject”) ; static Demo staticObject (“staticObject”) ; cout << “Inside func\n” ; }

30 Egy globális objektum definiálása
Demo globalObject (“globalObject”) ; void main() { Demo localMainObject (“localMainObject”) ; cout <<”In main, before calling func\n” ; func ( ) ; cout <<”In main, after calling func\n” ; }

31 A program a következőket nyomtatja ki:
Constructor called for globalObject Constructor called for localMainObject In main, before calling func Constructor called for localFuncObject Constructor called for staticObject Inside func Destructor called for localFuncObject In main, after calling func Destructor called for localMainObject Destructor called for staticObject Destructor called for globalObject

32 Téglalap osztály kialakítása
class CRectangle { int Left; //adattagok int Top; int Right; int Bottom;

33 void Draw(void) //metódus
{ Line (Left, Top, Right, Top); Line (Right, Top, Right, Bottom); Line (Right, Bottom, Left, Bottom); Line (Left, Bottom, Left, Top); } };

34 Hozzáférési módok class CRectangle { private: int Left; int Top;
int Right; int Bottom;

35 public: void Draw(void) { Line (Left, Top, Right, Top); Line (Right, Top, Right, Bottom); Line (Right, Bottom, Left, Bottom); Line (Left, Bottom, Left, Top); }

36 Konstruktorok public: CRectangle() { Left=Top=Right=Bottom=0; }
CRectangle( int L, int T, int R, int B) SetCoord(L, T, R, B);

37 Metódusok prototípusa
void Draw(void) ; void SetCoord(int L, int T, int R, int B); void GetCoord(int *L, int *T, int *R, int *B);

38 Metódusok definiálása
//Értékek beállítása void CRectangle::SetCoord(int L, int T, int R, int B) { L=min (max (0,L), 80); T=min (max (0,T), 25); R=min (max (0,R), 80); B=min (max (0,B), 25); R=max (R,L); B=max (B,T); Left=L; Top=T; Right=R; Bottom=B; }

39 Hasznos függvények int max (int value1, int value2);
{ return ( (value1 > value2) ? value1 : value2); } int min (int value1, int value2); int min(int value1, int value2) return ( (value1 > value2) ? value2 : value1);

40 Metódusok definiálása
// Értékek szolgáltatása void CRectangle:: GetCoord(int *L, int *T, int *R, int *B) { *L = Left; *T = Top; *R = Right; *B = Bottom; }

41 Objektumok definiálása
void main() { CRectangle Rect1(25,25,100,100); Rect1.Draw(); CRectangle Rect2;

42 Öröklés Az örököltetés szintaktikája:
class származtatott osztály_név: elérési mód bázis-osztály_név { // … }

43 Elérési módok a származtatásnál
public private protected

44 A származtatás: public
//Alaposztály class base { int x; public: void setx (int n ) { x=n; } void showx() { cout <<x << ‘\n’; } };

45 Származtatott osztály
class derived : public base { int y; public: void sety (int n ) { y=n; } void showy() { cout <<y << ‘\n’; } };

46 Publikus tagok elérése
main() { derived ob; ob.setx (10); //eléri az alaposztály tagjait ob.sety (20); //eléri a származtatott osztály tagjait ob.showx (); //eléri az alaposztály tagjait ob.showy (); //eléri a származtatott osztály tagjait return 0; }

47 A private tagok nem elérhetők
//Alaposztály class base { int x; public: void setx (int n ) { x=n; } void showx() { cout <<x << ‘\n’; } };

48 private tagra nem hivatkozhatunk!
class derived : public base { int y; public: void sety (int n ) { y=n; } void show_sum() { cout <<x+y << ‘\n’; } //hiba! //x private tag void showy() { cout <<y << ‘\n’; } };

49 A származtatás: private
//Alaposztály class base { int x; public: void setx (int n ) { x=n; } void showx() { cout <<x << ‘\n’; } };

50 Származtatott osztály
class derived : private base { int y; public: void sety (int n ) { y=n; } void showy() { cout <<y << ‘\n’; } };

51 Publikus tagok elérése
main() { derived ob; ob.setx (10); //hiba, ez privát a származtatott osztályban ob.sety (20); //eléri a származtatott osztály tagjait ob.showx (); //hiba, ez privát a származtatott osztályban ob.showy (); //eléri a származtatott osztály tagjait return 0; }

52 Megoldás az előző példára A származtatás: private
//Alaposztály class base { int x; public: void setx (int n ) { x=n; } void showx() { cout <<x << ‘\n’; } };

53 Származtatott osztály
class derived : private base { int y; public: void setxy (int n, int m ) {setx(n); y=m; } void showxy() {showx(); cout <<y << ‘\n’; } };

54 Publikus tagok elérése
main() { derived ob; ob.setxy(10,20); //eléri a származtatott osztály tagjait ob.showxy (); //eléri a származtatott osztály tagjait return 0; }

55 protected tagok elérése
//Alaposztály class samp { int a; protected: int b; public: int c; samp(int n, int m) { a=n; b=m;} int geta ( ) { return a; } int getb ( ) {return b;} };

56 Hozzáférés protected tagokhoz
main() { //ob.b=99; //hiba!!! ob.c=30; //OK. cout<< ob.geta() << ‘ ‘; cout<< ob.getb() << ‘ ‘<<ob.c<<‘\n’; return 0; }

57 protected tagok //Alaposztály class base { protected: int a,b; public:
void setab(int n, int m) { a=n; b=m;} };

58 Származtatott osztály
class derived : public base { public: void setc (int n) { c=n;} void showabc() { cout<<a<<‘ ‘ <<b<< ‘ ‘ <<c << ‘\n’; } };

59 Publikus tagok elérése
main() { derived ob; ob.setab(1,2); ob.setc (); Ob.showabc(); return 0; }

60 Konstruktorok, destruktorok és a származtatás
A bázis osztály és a származtatott osztályok is rendelkezhetnek konstruktorokkal és destruktorokkal. A konstuktorok végrahajtásának sorrendje a származtatásnak megfelelő sorrendben történik. A destruktorok végrehajtása a származtatás sorrendjével ellenkező sorrendben történik.

61 Konstruktorok paraméterei
Különböző esetek: Alaposztálynak és származtatott osztálynak nincs paramétere Alaposztálynak nincs paramétere Származtatott osztálynak nincs, de a bázis osztálynak van paramétere Bázis osztálynak is és a származtatott osztálynak is van paramétere.

62 Bázis és származtatott osztály konstruktorainak végrehajtási sorrendje
#include <stdio.h> class base { public: base() { cout << „Bázis osztály konstruktora\n”;} ~base (){ cout << „Bázis osztály destruktora\n”;} }; class derived: public base { public; derived (){ cout << „Származtatott osztály konstruktora\n”;n ~derived() { cout << „Származtatott osztály destruktora\n”;}

63 A konstruktorok és destruktorok lefutása
main () { derived o; return 0; } Output: Bázis osztály konstruktora Származtatott osztály konstruktora Származtatott osztály destruktora Bázis osztály destruktora

64 Paraméterek átadása #include <stdio.h> class base { int i;
public: base ( int n) { cout << „Bázis osztály konstruktora\n”; i=n;} ~base { cout << „Bázis osztály destruktora\n”;} void show() { cout <<i << ‘\n’; } };

65 class derived: public base {
int j; public; derived ( int n, int m) : base(m) { cout << „Származtatott osztály konstruktora\n”; j=n; } ~derived { cout << „Származtatott osztály destruktora\n”;} void showj () { cout<< j << ‘\n’;} };

66 Objektum létrehozása main() { derived o(10,20); o.showi(); o.showj();
return 0; }


Letölteni ppt "Osztály fogalom Új fogalom: osztály (class)."

Hasonló előadás


Google Hirdetések