Öröklődés Objektumok közötti speciális kapcsolat.

Slides:



Advertisements
Hasonló előadás
Osztály leszármaztatás
Advertisements

C++ programozási nyelv Gyakorlat hét
1 Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz.
Öröklődés 2..
© Kozsik Tamás Beágyazott osztályok A blokkstrukturáltság támogatása –Eddig: egymásba ágyazható blokk utasítások Osztálydefiníciók is egymásba.
Programozás alapjai.
Bevezetés a Java programozásba
Bevezetés a Java programozásba
Osztályok Garbage collection.  általában minden osztálynak vannak adattagjai és/vagy metódusai ◦ adattagok megadása:  [láthatóság] [static] [final]
Vizuális modellezés Uml és osztálydiagram UML eszközök
UNIVERSITY OF SZEGED D epartment of Software Engineering UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás II. 5. Gyakorlat Öröklődés, virtuális függvények,
Programozás II. 3. Gyakorlat C++ alapok.
UNIVERSITY OF SZEGED D epartment of Software Engineering UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás II. 6. Gyakorlat const, static, dinamikus 2D.
Fejlett Programozási Technológiák II. Világos Zsolt 12. gyakorlat.
Mutatók, tömbök, függvények
A Java programozási nyelvSoós Sándor 1/17 Java programozási nyelv 4. rész – Osztályok II. Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai.
A C++ programozási nyelvSoós Sándor 1/17 C++ programozási nyelv Gyakorlat - 7. hét Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet.
Java programozási nyelv 3. rész – Osztályok I.
A C++ programozási nyelvSoós Sándor 1/15 C++ programozási nyelv Gyakorlat hét Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet.
A C++ programozási nyelvSoós Sándor 1/12 C++ programozási nyelv Gyakorlat - 8. hét Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet.
Java programozási nyelv 5. rész – Osztályok III.
C# tagfüggvények.
C# osztályok Krizsán Zoltán 1.0.
C# tagfüggvények.
OOP ÖRÖKLŐDÉS, INTERFÉSZ
A JAVA TECHNOLÓGIA LÉNYEGE Többlépcsős fordítás A JAVA TECHNOLÓGIA LÉNYEGE Platformfüggetlenség.
Ficsor Lajos Template-ek CPP8/ 1 Template-ek. Ficsor Lajos Template-ek CPP8/ 2 A template fogalma Kiindulási probléma: tetszőleges típusokon kellene ugyanolyan.
Ficsor Lajos CPP6 / 1 Virtuális bázisosztály Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék.
Kivételkezelés a C++ nyelvben Bevezetés
Objektumorientált tervezés és programozás II. 3. előadás
Szoftvertechnológia alapjai Java előadások Förhécz András, doktorandusz tárgy honlap:
1 Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz.
Hernyák Zoltán Programozási Nyelvek II.
1 Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz.
1 Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz.
1 Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz.
Hernyák Zoltán Programozási Nyelvek II.
A D programozási nyelv Angeli Dávid. Nagy vonalakban  C++  
Javascript Microsoft által készített kiegészítése Statikus típusosság Nagy projektek Windows 8 fejlesztésénél WinRT egy részét ebben írták Nyílt forráskódú,
Java programozási nyelv Metódusok
Programozás III KOLLEKCIÓK.
Objektum orientált programozás
1 Objektum orientált programozás Struktúrák és objektumok gyakorlat Nagy Szilvia.
1 Objektum orientált programozás Öröklődés: többszörös öröklődés, konstruktorok, destruktorok, overloading Nagy Szilvia.
OOP ÖRÖKLŐDÉS, INTERFÉSZ
Programozás III OOP ÖRÖKLŐDÉS.
Programozás III KOLLEKCIÓK.
Objektumorientált alapjai ISZAM III.évf. részére Bunkóczi László.
Ficsor Lajos CPP2 / 1 Származtatási mechanizmus a C++ nyelvben Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék.
Ficsor Lajos A C++ programozási nyelv I. CPP1/ 1 Osztály és objektum fogalma.
Típuskonverzió a C++ nyelvben
Haladó C++ Programozás Programtervezési minták – alapok Sonkoly Balázs
Ficsor Lajos Objektumok inicializálása CPP4 / 1 Objektumok inicializálása Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék.
Objektum orientált programozás 4. Mutatók, típusok és struktúrák Nagy Szilvia.
Függvények, mutatók Csernoch Mária. Függvények függvény definíciója az értelmezési tartomány tetszőleges eleméhez hozzárendel egy értéket –függvény helyettesítési.
TÁMOP /1-2F JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam Osztályok, objektumok definiálása és alkalmazása. Saját.
Krizsán Zoltán, iit C# osztályok 2 Adattagok  Osztály hatáskörben definiált változó.  Formája: [attribútum] [módosító] típus azonosító [=kezdő érték][,
A szoftver mint komplex rendszer: objektumorientált megközelítés.
a programegységek között
A C++ programozási nyelv
Neumann János Informatikai Kar
Hernyák Zoltán Programozási Nyelvek II.
Beépített függvények használata programozáskor
JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam
Öröklés bemutatása Hozzunk létre egy Dolgozó adatbázist C++-ban!
String osztály létrehozása
JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam
Konverziós operátorok
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.
Függvénysablonok használata
Előadás másolata:

Öröklődés Objektumok közötti speciális kapcsolat. (Egy osztály a másik általánosításaként, vagy éppen specializált változataként jelenik meg.) Ember, diák, tanár.

Program készítése két módon: IS_A reláció. Program készítése két módon:      független osztály kialakítása     öröklődéssel történő definíció alaposztály származtatott osztály

Újrafelhasználhatóság Az öröklődéssel történő megoldás előnyei:   hasonlóság kiaknázása miatt a program egyszerűbb -  osztálykönyvtárak kialakítása, felhasználása (újrafelhasználhatóság).

Öröklődés leírása Ember név, kor Diák +átlag, évfolyam általánosít Ember név, kor az egy az egy Diák +átlag, évfolyam Tanár +fizetés, tárgy specializál

Geometriai alakzatok példája Shape hely, szín, Move() analitikus öröklés Rect +sarok, Draw() Line +vég, Draw() Circle +sugár, Draw() korlátozó öröklés Square

Alakzatok fajtái Általános alakzat: Shape. (szín, hely) Speciális alakzatok: Rect, Line, Circle

Általános alakzat osztálya class Shape {   protected: int x, y, col; public: Shape ( int x0, int y0, int col0 ) { x = x0; y = y0; col = col0; } void SetColor ( int c ) { col = c; } };

Line osztály class Line : public Shape { // Line = Shape + ... int xe, ye; public: Line( int x1, int y1, int x2, int y2, int c ) : Shape( x1, y1, c ) { xe = x2, ye = y2; }   void Draw( ); void Move (int dx, int dy ) ; };

Line osztály Draw() metódusa void Line :: Draw( ) {   // cout << "\nLine: " << x << ',' << y; // cout << " : " << xe << ',' << ye << " ; " << col; _SetColor (col ) ; // rajz a grafikus könyvtárral _MoveTo ( x,y ); _LineTo (xe, ye ) ; }

Line osztály Move() metódusa void Line :: Move( int dx, int dy ) {   int cl = col; //tényleges rajzolási szín elmentése col = BGD; //rajzolási szín legyen a háttér színe Draw( ); // A nonal letörlése az eredeti helyről x += dx; y += dy; // mozgatás: a pozíció változik col = cl; // a rajzolási szín a tényleges szín Draw( ); // A vonal felrajzolása az új pozícióra

Rect osztály class Rect : public Shape { // Rect = Shape + ...   int xc, yc; public: Rect( int x1, int y1, int x2, int y2, Color c ) : Shape( x1, y1, c ) { xc = x2, yc = y2; } void Draw( ); void Move ( int dx, int dy ) ; };

Rect osztály Draw() metódusa void Rect :: Draw( ) {   cout << "\nRect: " << x << ',' << y; cout << " : " << xc << ',' << yc << " ; " << col; }

Származtatással kapcsolatos fogalmak protected hozzáférés-módosító szó class Line :: public Shape {.....} - származtatás, szülő (ős), gyermek (származtatott) public és private jelentése. Származtatott osztályban a tagfüggvényeket újradefiniálhatjuk (ez felülbírálja az alaposztály ugyanilyen nevű tagfüggvényét.

Konstruktorok meghívása Line konstruktorának definíciója: Line( int x1, int y1, int x2, int y2, int c ) : Shape( x1, y1, c ) { xe = x2, ye = y2; } Definíció szerint az alaposztály konstruktora is meghívásra kerül.

Move függvény vizsgálata Vizsgáljuk meg az egyes osztályokban lévő Move függvényt! Ugyanaz, csak mindegyik más Draw() függvényt hív meg. Virtuális tagfüggvény!

Move() elhelyezése az ősosztályban class Shape {  protected: int x, y, col; public: Shape( int x0, int y0, int col0 ) { x = x0; y = y0; col = col0; } void SetColor( int c ) { col = c; } void Move ( int dx, int dy ) ; virtual void Draw ( ) { } };

Move() megvalósítása void Shape :: Move( int dx, int dy ) { int cl = col; //tényleges rajzolási szín elmentése col = BGD; //rajzolási szín legyen a háttér színe Draw( ); // A vonal letörlése az eredeti helyről x += dx; y += dy; // mozgatás: a pozíció változik col = cl; // a rajzolási szín a tényleges szín Draw( ); // A vonal felrajzolása az új pozícióra

Line osztály class Line : public Shape { // Line = Shape + ...   int xe, ye; public: Line( int x1, int y1, int x2, int y2, int c ) : Shape( x1, y1, c ) { xe = x2, ye = y2; } void Draw( ); };

Rect osztály class Rect : public Shape { // Rect = Shape + ...   class Rect : public Shape { // Rect = Shape + ... int xc, yc; public: Rect( int x1, int y1, int x2, int y2, Color c ) : Shape( x1, y1, c ) { xc = x2, yc = y2; } void Draw( ); };

Üzenetek objektumoknak void main ( ) {   Rect rect( 1, 10, 2, 40, RED ); Line line( 3, 6, 80, 40, BLUE ); Shape shape( 3, 4, GREEN ); shape.Move( 3, 4 ); // 2 db Draw hivás line.Draw( ); line.Move( 10, 10 ); // 2 db Draw hivás

Metódusok meghívása indirekten Shape * sp[10]; sp[0] = &rect; sp[1] = &line; // nem kell cast   for( int i = 0; i < 2; i++ ) sp[i] -> Draw( ); //indirekt Draw() }

Virtuális Shape::Draw Nem virtuális shape.Move() line.Draw() Line::Draw line.Move() sp[0] -> Draw(), mutatótípus Shape * de Line objektumra mutat sp[1] -> Draw(), de Rect objektumra mutat Rect::Draw

Szimuláció C programmal struct Shape { int x, y, col }; //Shape adattagjai   void Draw_Shape (struct Shape * this) {} //Shape::Draw

Move() szimulációja void Move_Shape (struct Shape * this, int dx, int dy) { //Shape::Move   int cl = this ->col; //tényleges rajzolási szín elmentése this ->col = BGD; //rajzolási szín legyen a háttér színe Draw_Shape( this ); // A vonal letörlése az eredeti helyről this ->x += dx; this ->y += dy; // mozgatás: a pozíció változik this ->col = cl; // a rajzolási szín a tényleges szín Draw_Shape( this ); // A vonal felrajzolása az új pozícióra }

Tisztán virtuális tagfüggvény - absztrakt alaposztály. class Shape {   protected: int x, y, col; public: Shape( int x0, int y0, int col0 ) { x = x0; y = y0; col = col0; } void SetColor( int c ) { col = c; } void Move ( int dx, int dy ) ; virtual void Draw ( ) = 0; };

Virtuális függvények Tegyük fel, hogy van egy A alaposztályunk és egy B származtatott osztályunk, amelyben az alaposztály f függvényét újradefiniáltuk.   class A { public: void f ( ); // A: :f }; class B : public A { void f ( ); // B: : f

Metódus kiválasztása Az objektum orientált programozás alapelve szerint egy üzenetre lefuttatott metódust a célobjektum típusa és az üzenet neve ( valamint az átadott paraméterek típusa ) alapján kell kiválasztani. Tehát, ha definiálunk egy A típusú a objektumot és egy B típusú b objektumot, és mindkét objektumnak f üzenetet küldünk, akkor azt várnánk el, hogy az a objektum esetében az A :: f, míg a b objektumra a B:: f tagfüggvény aktivizálódik. Vannak egyértelmű esetek, amikor ezt a kívánságunkat a C++ fordító program minden további nélkül teljesíteni tudja:

Objektumok definiálása { A a; B b;   a. f ( ) ; // A : : f hívás b. f ( ) ; // B : : f hívás }

Direkt üzenet küldése Ebben a példában az a.f ( ) A típusú objektumnak szól, mert az a objektumot az A a; utasítással definiáltuk. Így a fordítónak nem okoz gondot, hogy ide az A:: f hívást helyettesítse be. A C++ nyelvben azonban vannak olyan lehetőségek is, amikor a fordító program nem tudja meghatározni a célobjektum típusát. Ezek a lehetőségek a részint az indirekt üzenetküldést, részint az objektumok által saját maguknak küldött üzeneteket foglalják magukban. Nézzük először az indirekt üzenetküldést:

Indirekt üzenet küldése { A a ; B b; A * pa ;   if ( getchar ( ) = = 'i ' ) pa = & a ; else pa = & b; pa - > f ( ) ; // indirekt üzenetküldés }

Célobjektum meghatározása Az indirekt üzenetküldés célobjektuma, attól függően, hogy a program felhasználója az i billentyűt nyomta-e le, lehet az A típusú a objektum vagy a B típusú b objektum. Ebben az esetben fordítási időben nyilván nem dönthető el a célobjektum típusa. Megoldásként két lehetőség kínálkozik:

Nem virtuális eset   Kiindulva abból, hogy a pa mutatót A* típusúnak definiáltuk, jelentse ilyen esetben a pa -> f ( ) az A: : f tagfüggvény meghívását. Ez ugyan téves, ha a pa a b objektumot címzi meg, de ennél többre fordítási időben nincs lehetőségünk.

Virtuális eset 1Bízzuk valamilyen futási időben működő mechanizmusra annak felismerését, hogy pa ténylegesen milyen objektumra mutat, és ennek alapján futási időben válasszunk A : : f és B : : f tagfüggvények közül.  

Két lehetőség a C++-ban A C++ nyelv mindkét megoldást felkínálja, melyek közül aszerint választhatunk, hogy az f tagfüggvényt az alaposztályban normál tagfüggvénynek ( 1. lehetőség ), vagy virtuálisnál ( 2. lehetőség ) deklaráltuk. 

Önmagának szóló üzenet Hasonló a helyzet az "önmagukban beszélő" objektumok esetében is. Egészítsük ki az A osztályt egy g tagfüggvénnyel, amely meghívja az f tagfüggvényt.   class A { public: void f ( ) ; // A : : f void g ( ) { f ( ) ; ) };

B osztályban f átdefiniálása   class B : public A { public: void f ( ) ; // B : : f } ;

A::f() vagy B::f() meghívása A B típusú objektum változtatás nélkül örökli a g tagfüggvényt és újra definiálja az f-t. Ha most egy B típusú objektumnak küldenénk g üzenetet, akkor a saját magának, azaz az eredeti g üzenet célobjektumának küldene f üzenetet. Mivel az eredeti üzenet célja B típusú, az lenne természetes, ha ekkor a B::f hívódna meg. A tényleges célobjektum típusának felismerése azonban nyílván nem végezhető el fordítási időben. Tehát vagy lemondunk erről a szolgáltatásról és az f tagfüggvényt normálnak deklarálva a fordító a legkézenfekvőbb megoldást választja, miszerint a g törzsében mindig az A::f tagfüggvényt kell aktivizálni. Vagy pedig egy futási időben működő mechanizmusra bízzuk, hogy a g törzsében ismerje fel az objektum tényleges típusát és a meghívandó f-t ez alapján válassza ki.

Többszörös öröklődés (multiple inheritance) Irodai alkalmazottakat kezelő probléma: Alkalmazottak (Employee) Menedzserek (Manager) Ideiglenes alkalmazottak (Temporary) Ideiglenes menedzserek (Temporary manager)

Osztályok

Employee osztály class Employee { protected: char name[20]; long salary; public: Employee (char *nm, long sl) ( strcpy( name,nm ) ; salary = sl ; } };

Manager osztály class Manager : public Employee { int level ; public: Manager (char *nam, long sal, int lev) : Employee (nam, sal) ( level = lev; } } ;

Temporary osztály class Temporary : public Employee { int emp_time; Temporary (char *nam, long sal, int time ); : Employee (nam, sal ) { emp_time = time} };

Temp_Man osztály class Temp_Man : public Manager, public Temporary { Temp_Man (char *nam, long sal, int lev, int time) : Manager (nam, sal, lev), Temporary (nam, sal, time) {} };

Lehetséges elhelyezésük a memóriában

Nevek ütközése class A{ class B{ protected: protected: int x; int x; }; };   class C: public A, public B { int f() { x=3; x=5;} }; 

Többértelműség megszüntetése A többértelműség megszüntethető a scope operátor felhasználásával: int f() { { A::x=3; B::x=5;}    Azonos nevű adattagok összevonása ellen szól a kompatibilitás elvesztése.

Megoldás: class Manager: virtual public Employee {…}; class Temporary: virtual public Employee {…}; class Temp_Man: virtual public Manager, public Temporary { public: Temp_Man ( char * nam, long sal, int lev, int ti,e) :Employee (nam, sal), MAneger (NULL, 0L, lev), Temporary (NULL, 0L, ti,e) { } };

Memóriában való elhelyezésük

A konstruktor feladatai A virtuális alaposztályok konstruktorainak hívása, akkor is, ha a virtuális alaposztály nem közvetlen ős. A közvetlen, nem virtuális alaposztályok konstruktorainak hívása. A saját rész konstruálása A virtuálisan származtatott osztályok objektumaiban egy mutatót kell beállítani az alaposztály adattagjainak megfelelő részre. ha az objektumosztályban van olyan virtuális függvény, amely itt új értelmet nyer (azaz az osztály a virtuális függvényt újradefiniálja), akkor az annak megfelelő mutatókat a saját megvalósításra kell állítani. A tartalmazott objektumok konstruktorainak meghívása. A konstruktornak a programozó által megadott részei csak a fenti feladatok elvégzése után kerülnek végrehajtásra.

A destruktorok feladatai A destruktor programozó által megadott részének a végrehajtása. A komponensek megszüntetése a destruktoraik hívásával. A közvetlen, nem-virtuális alaposztályok destruktorainak hívása. A virtuális alaposztályok destruktorainak hívása.