next up previous contents
Elõre: Függvénymezõk aktivizálása Fel: Programozás C++-ban Vissza: Többrétûség (polimorfizmus)

Függvénymezõk definiálása

Ebben az alfejezetben az öröklés fogalmánál használt grafikus példát folytatjuk.

Az elõzõekben láthattuk, hogy egy osztálynak nemcsak adatmezõi, hanem függvénymezõi (function members) is lehetnek. Egy függvénymezõ nem más, mint egy, a class definíción belül deklarált függvény. (A függvénymezõket más OOP nyelvekben, például a Smalltalk-ban, vagy a Turbo Pascal-ban metódusoknak hívják).

Most deklaráljunk egy get_x azonosítójú függvénymezõt a point osztály számára. Ezt kétféleképpen tehetjük meg:

a)
vagy az osztály-definíción belül defináljuk a függvényt (ún. implicit inline függvényként),
b)
vagy az osztálydefiníción belül csak deklaráljuk, és azután valahol késõbb definiáljuk.
A két módszer különbözõ szintaxissal rendelkezik. Lássunk egy példát az elsõ lehetõségre:
            class point
                  { int       x;
                    int       y;
                    colortype color;
                    int       get_x(void) { return x; };
                    ....
                    // implicit inline definicio
                  };
Ez a fajta definíció alapértelmezésben inline függvényként definiálja a get_x-et. Ez az ún. implicit inline függvény definició. Figyeljük meg, hogy az implicit inline függvénydefiníció szintaxisa a hagyományos C-ben megszokottak szerinti.

A második lehetõségnél a C-szintaxissal csak deklaráljuk a get_x függvényt a point osztályban, és késõbb adjuk meg a függvény teljes definicióját:

            class point
                  { int       x;
                    int       y;
                    colortype color;
                    int       get_x(void);
                    // majd definialjuk
                    ....
                   };
            int point::get_x(void)
            {
               return x;
            }
            // Itt jobb lenne az implicit inline definicio
Figyeljük meg alaposan, hogy használtuk a :: hatáskört definiáló operátort (scope resolution operator) a point::get_x függvénydefinícióban. A point osztályazonosító szükséges ahhoz, hogy a fordítóprogram tudja, melyik osztályhoz is tartozik a get_x függvénydefiníciója, valamint tudja azt is, hogy mi az érvényességi tartománya. Ez tehát azt jelenti, hogy a pont::get_x függvény (a hagyományos globális változókon kívül) csak a point osztályhoz tartozó objektumok mezõihez férhet hozzá. Természetesen létezhet több, más osztályhoz tartozó get_x függvény is. (Erre a lehetõségre - bár nem explicit módon - utaltunk a többrétûség tárgyalásánál.) Az osztály-deklaráción belüli függvény-definició esetében természetesen nem volt szükség az érvényességi tartományt definiáló point:: elõtagra, hiszen a get_x függvény hovatartozása abban az esetben teljesen egyértelmû volt.

A hovatartozás definiálásán túlmenõen a point::-nak más szerepe is van. Hatása kiterjed az õt követõ függvénydefinícióra oly módon, hogy a get_x függvényen belül az x azonosítójú változóra való hivatkozás a point struktúra x azonosítójú adatmezõjére vonatkozik, valamint a get_x függvény a point osztály hatáskörébe kerül (lásd a 2.6.2-es részt).

Függetlenül attól, hogy a függvénymezõt milyen módon definiáljuk, a lényeg az, hogy van egy get_x nevû függvényünk, ami szorosan hozzá van kapcsolva a point névvel ellátott osztályhoz. Mivel a get_x-et mezõként definiáltuk a point számára, a point minden adatmezõjéhez hozzáférhet. Ebben az egyszerû példánkban get_x egyszerûen csak x értékét szolgáltatja.

Elképzelhetõ, hogy egy származtatott típusban lokálisan deklarálunk egy függvénymezõt, melynek azonosítója és paraméterlistája is megegyezik egy õstípusban definiált függvénymezõ azonosítójával és paraméterlistájával, ugyanakkor a definíció során fel szeretnénk használni az õstípusbeli változatot. Mivel a késõbbi definícióban lévõ függvénymezõ a saját hatáskörében elfedi a korábbi definíciót, a származtatott típusban csak az érvényességi tartományt defináló operátor segítségével használhatjuk az õstípusban definiált, "elfedett" függvénymezõt. Erre vonatkozóan (az eddigi példánkat egy kicsit félretéve) tekintsük az alábbi deklarációkat:

class rectangle { int   a, b;   // Negyszog adatai
                  ...
                  void  show(void); // Kirajzolja
                };
class triangle  { int   a, b, c;// Haromszog adatai
                  ...
                  void  show(void); // Kirajzolja
                };
class house : rectangle,        // Ostipusok
              triangle
                 {              // Egy hazat definial
                   ......       // Tetszoleges mezok
                   void show(void); // Kirajzolja
                 };
// Az egyes fuggvenymezok definicioi:
void rectangle::show( ) { ... } // Egy negyszoget rajzol
void triangle::show( )  { ... } // Egy haromszoget rajzol
void house::show( )             // Egy hazat rajzol
{
  // Itt az  egyszeru  'show'  azonosito  a  'house'  tipus
  // fuggvenymezojet jelenti, a 'show' hivas rekurzio lenne

  rectangle::show( ); // alap
  ...
  triangle::show( );  // teto
  ...
  ::show( ); // Egy globalis, 'show' fuggveny hivasa
};
Amint az fenti példából is látszik, ha egy hagyományos, nem egy osztály függvénymezõjeként deklarált show függvényt akarunk meghívni, akkor a függvénynév elé egy "üres" érvényességi tartományt definiáló operátort (::) kell tennünk (azaz nem utaljuk egy osztály hatáskörébe sem, így a teljes programra nézve globális lesz a függvény). Ezután a kitérõ után a foglalkozzunk tovább a megszokott point / location példával.
 



next up previous contents
Elõre: Függvénymezõk aktivizálása Fel: Programozás C++-ban Vissza: Többrétûség (polimorfizmus)