next up previous contents
Elõre: Többrétûség (polimorfizmus) Fel: Programozás C++-ban Vissza: Egységbezárás

Öröklés

Mi jut eszünkbe az öröklés szóról? Talán az, hogy a gyermek milyen tulajdonságokat örökölt szüleitõl, vagy gondolhatunk egy családfára is. Ugyanilyen családfa építhetõ fel osztályokkal is. A C++-ban deklarálhatók származtatott osztályok (derived classes), amelyek öröklik az õstípusok, az alaposztályok (base classes) adat- és függvénymezõit. Ez lehetõvé teszi egy hierarchikus osztálystruktúra létrehozását.

Nézzünk meg erre egy egyszerû példát. Ha grafikus programot készítünk, szükségünk lehet arra, hogy kezeljük a grafikus képernyõn egy pont (pixel) helyének x és y koordinátáit. Hozzunk ezért létre egy location (hely) nevû struktúrát:

            struct location {
                              int x;
                              int y;
                            };
Tegyük fel, hogy szükségünk van az x, y koordinátában lévõ pont tulajdonságára is, például nyilván akarjuk tartani, hogy egy kérdéses pont milyen szinû. Ezt megoldhatjuk a color (szín) felsorolt típusú változó bevezetésével. Így definiáljuk a point (pont) típust:
            enum   colortype { black, red,    blue,
                               green, yellow, white };
            struct point {
                            int       x;
                            int       y;
                            enum colortype color;
                         };
Ezek után deklarálhatunk point típusú változókat:
             struct point origin, center,
                          current_pos, new_pos;
A C++-ban a fenti deklarációt rövidebben is írhatjuk - lévén egy osztálydefinicónál megadott típuscímke önmagában is típus értékû:
              point origin, center,
                    current_pos, new_pos;
Mint láttuk, a point típusban is felhasználtunk olyan adatmezõket, amilyenek a location-ban szerepeltek. Jó lenne tehát, ha point definiálásához felhasználnánk a location típust. Nos, hagyományos C-ben a point-ot a location struktúra felhasználásával így definiálhatnánk:
            struct point {
                           struct location position;
                           colortype       color;
                         };
Ez nem más, mint struktúrák egymásbaágyazása (nested structures). Ugyanakkor a C++ esetében a deklarációban jelezhetjük, hogy a pont is egy hely. Ezt úgy tehetjük meg, hogy mind a point típust, mind a location típust class-ként definiáljuk, és point-ot a location-ból származtatjuk:
   class location 
                 {
                   protected: 
                       int x;
                       int y;
                 }
   class point : location  
                 {
                       colortype color;
                 };
Ez  a  deklaráció   sokkal   jobban kifejezi azt, hogy miben különbözik a point típus a location típustól. (A protected kulcsszó jelentését késõbb tárgyaljuk majd.) A különbség teljesen nyilvánvalóan abban van, hogy a point egy hely (location), amelyhez valamilyen színt is rendeltünk.

A képernyõn a pont helyzete a point definíciójában explicit módon nem szerepel, mert azt a location típustól örökölte.  Mivel a   point   típus   a location leszármazottja, annak minden mezõjét örökli, de ugyanakkor a színt leíró mezõvel bõvítettük. Egy származtatott típus definíciós blokkjában csak az új, vagy megváltozott tulajdonságoknak megfelelõ mezõk szerepelnek. Természetesen a point típusból újabb osztályokat származtathatunk úgy, hogy tovább bõvítjük tetszõleges típusú mezõkkel. Az így létrehozott típusok természetesen (az új tulajdonságaik mellett) hordozni fogják a point típus minden meglévõ tulajdonságát, és használhatók lesznek minden olyan esetben, amikor point is használható.

Azt az eljárást, amely által az egyik típus örökli a másik típus tulajdonságait, öröklésnek hívják. Az öröklõ a leszármazott típus ( descendant type). Az õstípus (ancestor type) az, amelytõl a leszármazott típus örököl.

Fenti példánkban a location az õstípus, a point pedig a leszármazott típus. Késõbb látni fogjuk, hogy ez az eljárás korlátlanul folytatható. Definiálhatjuk a point leszármazott típusát, majd ennek a point leszármazott típusának a leszármazottját. A programtervezés legnagyobb része az OOP-ben a megfelelõ osztály-hierarchiának, azaz az osztályok családfájának a létrehozását jelenti.

A point típus a location típusnak egy közvetlen leszármazottja (immediate descendants). Fordítva, a location típus a point típusnak közvetlen õstípusa ( immediate ancestor). Egy objektumtípusnak bármennyi közvetlen leszármazottja lehet.

Az öröklés szintaktikailag a következõképpen nyilvánul meg. Tegyük fel, hogy az alfa azonosítójú, point típusú objektum x koordinátájára szeretnénk hivatkozni. Ezt a point típus hagyományos C szerinti beágyazott struktúrákkal történõ definciója esetén az alfa.position.x módon tehetnénk meg, míg C++-ban, mivel a point típus mindent örököl a location típustól, az alfa.x kifejezés a megfelelõ hivatkozás.

Mint ahogy a C-ben egy típussal, a C++-ban a point osztály segítségével tetszõleges tárolási egységeket (újabb osztályokat, változókat, tömböket, osztályokra mutató pointereket, stb.) definiálhatunk, így jutva különbözõ objektum-példányokhoz:

            point origin, line[80],
            point *point_ptr1 = &origin;
            point *point_ptr2 = line;
A C++-ban egy származtatott típus nemcsak egy õstípustól örökölhet (egy családfán pl. minden egyednek van apja is és anyja is). Azt, amikor egy származtatott típus több õstípusból került levezetésre, többszörös öröklésnek (multiple inheritance) nevezzük. A többszörös öröklés csak az AT&T 2.0-ás verziójú C++ fordítójával kompatibilis C++ rendszerekben lehetséges. Többszörös öröklés esetén az õstípusokat egymástól vesszõvel elválasztva kell felsorolnunk. Ha tehát father és mother egy-egy létezõ osztály (például class-ként definiált típus), akkor segítségükkel a child típust a következõképpen deklarálhatjuk:
            class child : father, mother
                  {
                   // Itt jonnek a 'child'-ra jellemzo
                   // ujabb tulajdonsagok mezoi.
                  };
A child tehát örökli a father és a mother minden tulajdonságát (azaz minden adat- és függvénymezõjét), és egyben újabb tulajdonságokkal (mezõkkel) rendelkezhet.

A mezõhozzáférés kapcsán a 2.8-as szakaszban látni fogjuk, hogy egy származtatott típusban az õstípusoktól örökölt függvénymezõk hozzáférési szintjei módosíthatók az õstípus-listában a típusazonosítók elõtt elhelyezett megfelelõ kulcsszavakkal ( private, protected).

Mivel a származtatott típusokkal mindent olyan mûvelet elvégezhetõ, ami a definiciója során felhasznált õstípusokhoz felhasználható, ezért egy származtatott típus mindig felülrõl kompatibilis az õstípusaival.

Összefoglalva tehát a fent leírtakat: Hagyományos C-ben egy struktúra nem tud örökölni, a C++ azonban támogatja az öröklést. A nyelvnek ez a kiterjesztése egy új tárolási egység-fajtában nyilvánul meg, amely hasonló a C-ben megszokott tárterületfoglaló tárolási egységekhez, a struktúrákhoz és a -unionokhoz, de azoknál sokkal hatékonyabb. A tárolási egységek ezen új fajtája az osztály. Hatékonysága abban áll, hogy míg a hagyományos C-ben hierarchikusan egymásbaágyazott struktúrarendszerben csak adatmezõk "öröklõdnek", addig a C++ osztályok esetében egy objektum egyéb tulajdonságai - nevezetesen az, hogy az adatmezõkkel mit és hogyan lehet csinálni - is (azaz a függvénymezõk is) öröklõdnek. Megjegyzendõ, hogy a hagyomános C egymásba skatulyázott struktúrái esetében nincs szó igazi öröklésrõl, és a skatulyázás révén definiált újabb struktúrák, és a definiáláshoz felhasznált struktúrák között semmiféle típuskompatibiltás nincs.

A C++ osztályok típus-kompatibilitását a point - location páros felhasználásával az alábbiakban szemléltethetjük: egy point osztályba tartozó változó minden olyan esetben alkalmazható, amikor egy location osztályba tartozó érteket várunk. Tehát a

            location *a;
            point     b;
deklaráció mellett C++-ban az a = &b értékadás helyes, míg hagyományos C-ben, ha point és location egy-egy struktúra, akkor a fenti értékadás helytelen.


next up previous contents
Elõre: Többrétûség (polimorfizmus) Fel: Programozás C++-ban Vissza: Egységbezárás