Posljednja izmjena: 06.03.2002


Nasljeđivanje razreda

Sintaksa nasljeđivanja
Nasljeđivanjem se omogućuje korištenje nekih članova i metoda osnovnog razreda od strane izvedenog razreda. Nasljeđivanje se u C++ realizira navođenjem imena osnovnog razreda iza imena izvedenog razreda kako slijedi:

 class OsnovniRazred
 { ... }

 class IzvedeniRazred : public OsnovniRazred
 { ... }

Kao modifikator pristupa mogu se navesti ključne riječi public, private ili protected, koje tada mijenjaju pristup članovima objekta izvedenog razreda iz drugih dijelova programa. Tablica izvođenja je sljedeća:

izvođenje sa  pristup u osnovnom r.  pristup u izvedenom r.
public public public
protected protected
private private
protected public protected
protected protected
private private
private public private
protected private
private private

Npr. ako je neki član u osnovnom razredu bio public, dakle moglo mu se pristupiti iz bilo kojeg dijela programa, a modifikator izvođenja je protected, tada se tom članu neće moći pristupiti preko objekta izvedenog razreda jer je tamo postao protected, dok mu se način pristupa u osnovnom razredu ne mijenja.
Unutar metoda izvedenog razreda može se pristupati svim public ili protected članovima osnovnog razreda, dok se private članovima ne može pristupiti.
Jednostruko ili jednostavno nasljeđivanje je takvo nasljeđivanje kod koga izvedeni razred ima samo jedan osnovni razred. U sljedećem primjeru razred koji predstavlja realni broj korišten je kao osnova razredu koji će dodati operator zbrajanja; drugim riječima, razred RBr_Zbrajanje je naslijedio razred RBr:

class RBr
{   protected:
        double r;
    public:
        void Set(double _r)
        { r=_r; }
        double Get(void)
        { return r; }
};

class RBr_Zbrajanje: public RBr
{   public:
        RBr_Zbrajanje operator+ (const RBr_Zbrajanje& op2)
        {   RBr_Zbrajanje rezultat;
            rezultat.r=(*this).r+op2.r;
            return rezultat;
        }
};
...
RBr_Zbrajanje a,b,c;
a.Set(1); // koristimo metodu osnovnog razreda
b.Set(2);
c=a+b;
c.Get();

Razred izveden iz nekoga drugoga osnovnog razreda nasljeđuje sve njegove članove i metode, tako da se metode mogu pozivati i preko objekata izvedenog razreda. Konstruktori i destruktori se ne nasljeđuju. Pri inicijalizaciji objekta izvedenog razreda implicitno se pozivaju i konstruktor izvedenog i osnovnog razreda.
 

Polimorfizam i virtualne funkcije
Nasljeđivanjem razreda možemo konstruirati hijerarhijsku strukturu koja će nam poslužiti za lakše oblikovanje programskog koda. Zajednička svojstva grupe razreda mogu biti sadržana u jednom ili više nadrazreda iz koga su ostali izvedeni. Imamo li više izvedenih razreda, možemo pojednostaviti rukovanje s njima koristeći pokazivač ili referencu na osnovni razred. Pokazivač tipa osnovnog razreda može, osim na objekte osnovnog razreda, pokazivati i na bilo koji objekt izvedenih razreda, kojima nije jednak po tipu. Ovisno o vrsti objekta na koji pokazuje, prevodilac može različito interpretirati upotrebu takvog pokazivača (polimorfizam).

 OsnovniR *p;
 IzvedeniR1 a;
 IzvedeniR2 b;
 p=&a;
 p=&b;
 p=new IzvedeniR3;

Izvedeni razred moći će koristiti public i protected metode osnovnog razreda, ali se te metode također mogu i nadopuniti ili čak nanovo definirati u izvedenom razredu. Ispred deklaracije metode osnovnog razreda koja će biti redefinirana u nekom izvedenom razredu potrebno je staviti ključnu riječ virtual. Tada će prevodilac pozvati istoimenu metodu izvedenog razreda, čak i kada je pokazivač, koji pokazuje na objekt izvedenog razreda, po tipu osnovnog razreda.

class Osnovni
{   public:
        virtual void virt_fun(void)
        { ... }
        void fun(void)
        { ... }
};
class Izvedeni
{   public:
        void virt_fun(void)
        { ... }
        void fun(void)
        { ... }
};

...
Osnovni *p = new Izvedeni;
p->fun();      // izvrsit ce se funkcija Osnovni::fun()
p->virt_fun(); // izvrsit ce se funkcija Izvedeni::virt_fun()
...
p->Osnovni::virt_fun()
// ako bas zelimo pozvati funkciju iz osnovnog razreda, mozemo joj
// pristupiti operatorom dosega ::

U tijelu redefinirane metode u izvedenom razredu možemo također pozvati i istoimenu metodu osnovnog razreda (npr. ako je dio posla koji obavljamo identičan) sa:

void Izvedeni::virt_fun()
{   ...
    Osnovni::virt_fun();
    ...
}