6.1 naslijeđivanje

18
NASLIJEĐIVANJE Naslijeđivanje je jedna od najvažnijih ideja u objektnim programskim jezicima (a samim time i u jeziku C++). Mogućnosti koje naslijeđivanje nudi su izuzetno velike. Programski kod postaje jasnije organiziran, ugrađivanje novih mogućnosti je jednostavno i povećava se ponovna iskoristivost koda. U nastavku će biti objašnjeni osnovni principi naslijeđivanja. JEDNOSTAVNO JEDNOSTRUKO NASLIJEĐIVANJE Naslijeđivanje se koristi pri pisanju nove klase. Moguće je definirati da se nova klasa izvodi iz druge klase. Pod time se misli da nova klasa automatski prima sva svojstva klase iz koje se izvodi. Drugim riječima, izvedena klasa ima sve članove (i podatkovne i funkcijske) koje posjeduje i klasa iz koje je izvedena. Nova klasa, tj. klasa koja se izvodi se zove izvedena klasa (ili derivirana klasa). Klasa iz koje se izvodi se zove bazna klasa. U osnovnoj ideji, bazna klasa pruža temelj na koji će izvedena klasa dodati nova proširenja. Pretpostavimo da smo napisali klasu Osoba koja sadrži slijedeće članove: ime, prezime i JMBG zajedno sa pripadnim pristupnim (set i get) metodama. Pretpostavimo sada da želimo napisati novu klasu Radnik koja mora sadržavati sve članove koje sadrži klasa Osoba, ali i dodatne članove (npr. plaća radnika). Možemo se poslužiti već napisanom klasom Osoba koja ima definiran dio podataka koji trebaju klasi Radnik. U terminologiji naslijeđivanja to znači da ćemo klasu Radnik izvesti iz klase Osoba (klasa Radnik je izvedena klasa, dok je klasa Osoba bazna klasa). Jednostavnije rečeno, klasa Radnik će uzeti klasu osoba kao bazu i napraviti nova proširenja (u ovom jednostavnom primjeru će se dodati još jedan podatkovni član i dvije pristupne metode). Važno je primjetiti slijedeće: pri naslijeđivanju se sama bazna klasa ne mijenja. Klasa Osoba će raditi točno onako kako je radila i prije nego što je iz nje izvedena nova klasa. SINTAKSA NASLIJEĐIVANJA Naslijeđivanje se upotrebljava u trenutku kada se deklarira nova klasa. Pri deklaraciji nove klase može se navesti koja je bazna klasa. To se izvodi na slijedeći način: class Radnik : public Osoba { // deklaracije članova };

Upload: api-3759825

Post on 07-Jun-2015

223 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 6.1 Naslijeđivanje

NASLIJEĐIVANJE

Naslijeđivanje je jedna od najvažnijih ideja u objektnim programskim jezicima (a samim time i u jeziku C++). Mogućnosti koje naslijeđivanje nudi su izuzetno velike. Programski kod postaje jasnije organiziran, ugrađivanje novih mogućnosti je jednostavno i povećava se ponovna iskoristivost koda. U nastavku će biti objašnjeni osnovni principi naslijeđivanja.

JEDNOSTAVNO JEDNOSTRUKO NASLIJEĐIVANJE

Naslijeđivanje se koristi pri pisanju nove klase. Moguće je definirati da se nova klasa izvodi iz druge klase. Pod time se misli da nova klasa automatski prima sva svojstva klase iz koje se izvodi. Drugim riječima, izvedena klasa ima sve članove (i podatkovne i funkcijske) koje posjeduje i klasa iz koje je izvedena. Nova klasa, tj. klasa koja se izvodi se zove izvedena klasa (ili derivirana klasa). Klasa iz koje se izvodi se zove bazna klasa. U osnovnoj ideji, bazna klasa pruža temelj na koji će izvedena klasa dodati nova proširenja. Pretpostavimo da smo napisali klasu Osoba koja sadrži slijedeće članove: ime, prezime i JMBG zajedno sa pripadnim pristupnim (set i get) metodama. Pretpostavimo sada da želimo napisati novu klasu Radnik koja mora sadržavati sve članove koje sadrži klasa Osoba, ali i dodatne članove (npr. plaća radnika). Možemo se poslužiti već napisanom klasom Osoba koja ima definiran dio podataka koji trebaju klasi Radnik. U terminologiji naslijeđivanja to znači da ćemo klasu Radnik izvesti iz klase Osoba (klasa Radnik je izvedena klasa, dok je klasa Osoba bazna klasa). Jednostavnije rečeno, klasa Radnik će uzeti klasu osoba kao bazu i napraviti nova proširenja (u ovom jednostavnom primjeru će se dodati još jedan podatkovni član i dvije pristupne metode). Važno je primjetiti slijedeće: pri naslijeđivanju se sama bazna klasa ne mijenja. Klasa Osoba će raditi točno onako kako je radila i prije nego što je iz nje izvedena nova klasa.

SINTAKSA NASLIJEĐIVANJA

Naslijeđivanje se upotrebljava u trenutku kada se deklarira nova klasa. Pri deklaraciji nove klase može se navesti koja je bazna klasa. To se izvodi na slijedeći način:

class Radnik : public Osoba{ // deklaracije članova};

Ovom deklaracijom se navodi da se klasa Radnik izvodi iz klase Osoba. Drugim riječima, klasa Radnik automatski prima sve članove i metode koje se nalaze u klasi Osoba. Da bi ova deklaracija bila ispravna, potrebno je da se deklaracija klase Osoba nalazi prije deklaracije klase Radnik (ovo se najčešće izvodi tako da se deklaracija bazne klase spremi u posebnu .H datoteku te se na početku programa pomoću #include direktive uključi dotična datoteka).

Ovakvo naslijeđivanje se još zove i javno naslijeđivanje (zbog upotrebe ključne riječi public). Postoje još i zaštićeno i privatno naslijeđivanje, ali o njima nešto kasnije.

JAVNO NASLIJEĐIVANJE

Pri javnom naslijeđivanju vidljivost pojedinih članova se mijenja u izvedenoj klasi po određenim pravilima. Točnije, izvedena klasa prima sve članove koje se nalaze u izvedenoj klasi, ali "ne vidi" tj. ne može direktno pristupiti svim članovima. Pravilo je jednostavno: članovi koji su privatni u baznoj klasi se "ne vide" u izvedenoj klasi. Pod time se smatra da metode izvedene klase ne mogu pristupiti tim članovima (isto naravno vrijedi i za funkcije koje se nalaze van obje klase). Promotrimo slijedeći primjer:

Page 2: 6.1 Naslijeđivanje

class Osoba{ private:

char ime[20],prezime[20], JMBG[14];

public:const char *get_ime() const;void set_ime(const char *n_ime);

const char *get_prezime() const;void set_prezime(const char *n_prezime);

const char *get_JMBG() const;void set_JMBG(const char *n_JMBG);

};

class Radnik : public Osoba{ private:

float placa; public:

float get_placa() const;void set_placa(float n_placa);

};

Klasa Radnik sadrži sve članove koje sadrži i klasa Osoba. Međutim, iz njenih metoda ne može se direktno pristupiti članovima ime, prezime i JMBG. S druge strane, metode bazne klase su javne. Metoda izvedene klase može pozvati metodu bazne klase i preko nje promijeniti ili pročitati vrijednost privatnog člana bazne klase.

ZAŠTIĆENI ČLANOVI

Osim što članovi klase mogu biti public i private, postoje i tzv. protected tj. zaštićeni članovi. Za njih vrijede slijedeća pravila pristupa:

1. Zaštićenom članu mogu pristupiti sve metode bazne klase.2. Zaštićenom članu mogu pristupiti sve metode izvedene klase.3. Metode koje nisu u baznoj niti u izvedenoj klasi ne mogu pristupiti zaštićenom članu.

Može se reći da je zaštićeni član blaži oblik u odnosu na privatni. Naime zaštićeni članovi i dalje ostaju "nevidljivi" izvan same klase (npr. iz main funkcije se ne može direktno pristupiti zaštićenom članu). S druge strane, izvedene klase mu mogu direktno pristupiti. Sintaksa za deklaraciju zaštićenih članova je slična onoj za javne i privatne članove:

class Bazna{ private:

// privatni članovi

protected:// zaštićeni članovi

public:// javni članovi

};

Važno je uočiti da se protected članovi deklariraju u baznoj klasi ukoliko se želi izvedenoj klasi omogućiti pristup do njih, a ostalim dijelovima programa (tj. ostalim klasama i funkcijama) se želi zabraniti direktan pristup do njih.

Sada se mogu navesti i opća pravila pristupa članovima kod javnog naslijeđivanja:

Page 3: 6.1 Naslijeđivanje

1. Izvedena klasa prima sve članove koji se nalaze u baznoj klasi.2. Članovima koji su privatni u baznoj klasi mogu direktno pristupiti samo metode bazne

klase.3. Članovi koji su zaštićeni u baznoj klasi ostaju zaštićeni i u izvedenoj klasi. To zapravo

znači da im mogu pristupiti samo metode bazne i izvedene klase.4. Članovi koji su javni u baznoj klasi ostaju javni i u izvedenoj klasi. Drugim riječima tim

članovima mogu pristupiti svi.

Još jednom je potrebno istaknuti da naslijeđivanje utječe samo na izvedenu klasu. U ranijem primjeru, nakon što su deklarirane obje klase (Osoba i Radnik), klasa Osoba nije "dobila" član placa i pripadne pristupne metode. Te metode se nalaze u klasi Radnik.

Slijedeći primjer pokazuje kako se u glavnom programu može iskoristiti izvedena klasa Radnik:

main(){ Radnik ivo;

// učitavanje podataka ivo.set_ime(ime); // poziv javne metode bazne klase ivo.set_prezime(prezime); // poziv javne metode bazne klase ivo.set_jmbg(jmbg); // poziv javne metode bazne klase ivo.set_placa(placa); // poziv javne metode izvedene klase // ostatak programa}

POZIVI KONSTRUKTORA I DESTRUKTORA U IZVEDENOJ KLASI

Važno je primjetiti da se izvedena klasa sastoji iz dva dijela. Prvo, izvedena klasa sadrži u sebi baznu klasu, a uz to ona sadrži i proširenja (tj. nove članove). Ukoliko i izvedena i bazna klasa sadrže konstruktore, pri konstrukciji objekta izvedene klase će se prvo izvršiti konstruktor bazne klase, a zatim konstruktor izvedene klase. Obrnuto, kada se objekt izvedene klase uklanja iz memorije, prvo će se pozvati destruktor izvedene klase, a potom i destruktor bazne klase. Poziv konstruktora ilustrira slijedeći primjer:

class Osoba{ private:

char ime[20],prezime[20], JMBG[14];

public:const char *get_ime() const;void set_ime(const char *n_ime);

const char *get_prezime() const;void set_prezime(const char *n_prezime);

const char *get_JMBG() const;void set_JMBG(const char *n_JMBG);

Osoba() // konstruktor klase Osoba{ strcpy(ime,""); strcpy(prezime,""); strcpy(JMBG,"");

Page 4: 6.1 Naslijeđivanje

};};

class Radnik : public Osoba{ private:

float placa; public:

float get_placa() const;void set_placa(float n_placa);

Radnik(){ placa = 0;};

};

U trenutku kada se stvara novi objekt izvedene klase:

Radnik x;

prvo se poziva konstruktor klase Osoba, a zatim konstruktor klase Radnik. Konstruktor klase Osoba se poziva jer je klasa Osoba bazna klasa za klasu Radnik.

PROSLIJEĐIVANJE ARGUMENATA KONSTRUKTORU BAZNE KLASE

Posebna je situacija kada konstruktor izvedene klase ne prima iste argumente koje prima i konstruktor bazne klase. Ovo se ilustrira slijedećim primjerom:

class Osoba{ private:

char ime[20],prezime[20], JMBG[14];

public:const char *get_ime() const;void set_ime(const char *n_ime);

const char *get_prezime() const;void set_prezime(const char *n_prezime);

const char *get_JMBG() const;void set_JMBG(const char *n_JMBG);

Osoba(const char *n_ime, const char n_prez, const char *n_jmbg);};

Osoba::Osoba(const char *n_ime, const char n_prez, const char *n_jmbg){ strcpy(ime,""); strcpy(prezime,""); strcpy(JMBG,"");}

Page 5: 6.1 Naslijeđivanje

class Radnik : public Osoba{ private:

float placa; public:

float get_placa() const;void set_placa(float n_placa);

Radnik(const char *n_ime, const char n_prez, const char *n_jmbg, float n_placa);

};

Radnik::Radnik(const char *n_ime, const char n_prez, const char *n_jmbg, float n_placa) : Osoba(n_ime, n_prez, n_jmbg){ placa = n_placa;}

Konstruktor bazne klase prima tri argumenta (početne vrijednosti za ime, prezime i jmbg). S druge strane, konstruktor izvedene klase prima četiri argumenta. Zadatak konstruktora izvedene klase je da proslijedi konstruktoru bazne klase potrebne podatke. Proslijeđivanje se izvodi pri definiciji konstruktora izvedene klase. Iza liste argumenata slijedi znak : nakon čega se navodi ime konstruktora bazne klase te se unutar zagrada proslijeđuju potrebni argumenti. Uočite da u ovom primjeru se pri stvaranju novog objekta Radnik može pozvati samo konstruktor koji prima četiri argumenata. Drugim riječima slijedeća naredba je neispravna:

Radnik ivo("Ivo", "Ivic", "1234567890123");

Naime, klasa Radnik ima samo konstruktor koji prima četiri argumenta. Klasa Osoba ima konstruktor koji prima tri argumenta, međutim mi ovdje želimo stvoriti objekt klase Radnik a ne objekt klase Osoba.

ZAOBILAŽENJE METODA BAZNE KLASE

U osnovnoj ideji naslijeđivanja, izvedena klasa gradi proširenja oko temelja koji joj pruža bazna klasa. Može se reći da je izvedena klasa ustvari proširenje bazne klase. Moguće je međutim i da izvedena klasa redefinira neku od metoda bazne klase. Drugim riječima, moguće je u izvedenoj klasi napisati neku metodu koja već postoji u baznoj klasi. Kaže se da izvedena klasa zaobilazi metodu bazne klase. U slijedećem primjeru će se u klasu Osoba ugraditi metoda Ispis koja ispisuje iznose svih članova klase. Klasa Radnik će zaobići tu metodu (jer je potrebno ispisati još jedan član više).

class Osoba{ // deklaracija ostalih članova i metoda

public:void ispisi(){ cout << ime << " " << prezime << " " << jmbg;};

};

Page 6: 6.1 Naslijeđivanje

class Radnik : public Osoba{ // deklaracija ostalih članova i metoda

public:void ispisi(){ cout << get_ime() << " " << get_prezime() << " " <<

get_JMBG() << " " << placa;};

};

Kaže se da je klasa Radnik zaobišla metodu ispisi bazne klase.

U glavnoj funkciji je ove klase moguće upotrijebiti na slijedeći način:

Osoba x;Radnik y;

x.ispisi();y.ispisi();

Prvom naredbom se poziva metoda ispisi klase Osoba. Drugom naredbom se poziva metoda ispisi klase Radnik. Kada u klasi Radnik ne bi definirali metodu ispisi svejedno bi bilo moguće pozvati metodu s tim nazivom zbog toga što bazna klasa posjeduje javnu metodu ispisi. Međutim, na zaslon se ne bi ispisala plaća radnika (jer metoda bazne klase to ne radi).

Uočite da metoda izvedene klase može doći do sadržaja članova ime, prezime i JMBG samo preko pristupnih metoda bazne klase. To je iz razloga što su ti članovi (u ranijim primjerima) u baznoj klasi proglašeni privatnima.

Pažljivijim promatranjem može se primjetiti da izvedena metoda ispisi obavlja sav posao koji obavlja i bazna klasa. Kao posljedica, ispis podataka o osobi se pojavljuje na dva mjesta. Iz metode izvedene klase moguće je posebno pozvati metodu istog naziva koja se nalazi u baznoj klasi. Drugim riječima, metoda može (ali i ne mora) pozvati metodu koju zaobilazi. Ovo se obavlja na slijedeći način:

class Radnik : public Osoba{ // deklaracija ostalih članova i metoda

public:void ispisi(){ Osoba::ispisi(); // poziv bazne metode

cout << " " << placa;};

};

Metoda ispisi izvedene klase prvo poziva metodu koju zaobilazi (tj. metodu ispisi klase Osoba). Ovo se isplati jer bazna metoda ispisuje dio podataka koji treba ispisati izvedena metoda ispisi. Poziv bazne metode se izvodi na taj način da se navede naziv bazne klase iza čega slijedi operator :: te naziv metode (i eventualni potrebni argumenti). Ovakva posebna sintaksa je potrebna samo kada se iz metode izvedene klase poziva metoda bazne klase koja je zaobiđena u izvedenoj klasi. Ukoliko bazna metoda nije zaobiđena u izvedenoj klasi, ona se može pozvati kao i svaka druga metoda izvedene klase - samo preko naziva (uz eventualno navođenje argumenata).

Page 7: 6.1 Naslijeđivanje

GRAĐENJE OSNOVNE HIJERARHIJE

Dozvoljeno je, a u praksi i vrlo često, da više različitih izvedenih klasa imaju istu baznu klasu. Također je moguće da izvedena klasa služi kao bazna klasa nekoj drugoj klasi. Npr. za prethodni primjer, moguće je izvesti novu klasu Ucitelj iz klase Radnik. U takvoj situaciji, klasa Ucitelj se sastoji od tri dijela: klasa Osoba, klasa Radnik te proširenja koja se nalaze u samoj klasi Ucitelj. Na ovaj način moguće je izgraditi proizvoljno veliku hijerarhiju klasa koja počinje od jednostavne bazne klase na temelju koje se dalje grade nove klase sa proširenim mogućnostima. Slijedeći dijagram prikazuje jednu jednostavnu hijerarhiju:

Osoba

Radnik Ucenik

Ucitelj

Ovo je tzv. hijerarhijski dijagram koji prikazuje samo koji je međusobni odnos klasa u naslijeđivanju (koja je bazna klasa, a koja izvedena). Ovaj dijagram se čita na slijedeći način: klasa Osoba je bazna klasa za klase Radnik i Ucenik. Dodatno, klasa Radnik je bazna klasa za klasu Ucitelj.

KOMPATIBILNOST KLASA

Važno je primjetiti da je izvedena klasa "kompatibilna" sa baznom klasom. Drugim riječima izvedena klasa posjeduje sve članove i metode koje posjeduje i bazna klasa. Kao poslijedica toga, slijedeći kod je ispravan:

Osoba os;Radnik rad;

os = rad;

Uočite da su varijable različitog tipa. Kada se izvrši ove naredbe, događa se tzv. "rezanje". Naime, u objekt os (objekt bazne klase) se pohranjuje bazni sadržaj objekta rad (izvedene klase). Pod pojmom bazni sadržaj misli se na članove koji se nalaze u baznoj klasi. Ovaj odnos vrijedi općenito kroz cijelu hijerarhiju. Vidjeli smo da je klasa Radnik kompatibilna sa klasom Osoba. Međutim, vrijedi i da je klasa Ucitelj kompatibilna sa klasom Osoba.

Page 8: 6.1 Naslijeđivanje

VIRTUALNE METODE

Metoda se može deklarirati kao virtualna čime se posebno označava da se metoda u izvedenim klasama može zaobići. Za primjer će u nastavku biti napravljena hijerarhija klasa za prikaz geometrijskih likova u memoriji. Prvo krećemo od osnovne klase koja predstavlja općeniti geometrijski lik:

class Lik{ public:

virtual float povrsina();};

float Lik::povrsina(){ return 0;}

Klasa Lik se sastoji od jednog člana: metoda povrsina je zadužena da vrati površinu lika. Nove klase će biti izvedene iz klase Lik i zaobići tu metodu. Metoda je deklarirana kao virtualna (modifikator virtual) čime se označava da je izvedene klase mogu zaobići. Uočite da se ključna riječ virtual javlja samo u deklaraciji metode. Sada ćemo iz klase Lik izvesti dvije klase: Kvadrat i Krug.

class Kvadrat : public Lik{ private:

float a;

public:float povrsina() {return a * a;};// ostale metode za postavljanje dimenzija kvadrata

};

class Krug : public Lik{ private:

float r;

public:float povrsina() {return 3.14 * r * r;};

};

Ovakvo naslijeđivanje smo već ranije vidjeli. Izvedene klase konkretiziraju baznu klasu: dodaju svoje vlastite privatne članove i zaobilaze metodu povrsina kako bi ona radila ispravno u konkretnim slučajevima. Bitno je napomenuti da u izvedenim klasama nismo označili metodu povrsina kao virtualnu. To smo već napravili u baznoj klasi.

Sada možemo vidjeti kako se ovakva hijerarhija može upotrijebiti. Za početak, napišimo funkciju koja ispisuje površinu lika na zaslon:

void IspisPov(Lik *pLik){ cout << "Povrsina lika iznosi: " << pLik->povrsina()

<< endl;}

Page 9: 6.1 Naslijeđivanje

Main funkcija će imati slijedeći oblik:

main(){ Kvadrat kvad;

// popunjavanje dimenzija kvadrata

IspisPov(&kvad);

Krug y;

// popunjavanje dimenzija kruga

IspisPov(&krug);}

Ovaj kod ilustrira jedan zanimljiv pristup. Uočite da funkcija IspisPov prima pokazivač na klasu Lik. Iz glavne funkcije, mi šaljemo adresu objekta klase Kvadrat i klase Krug. To je moguće zato što su te dvije klase izvedene iz klase Lik te su kompatibilne sa njom. Važna činjenica je da pri ovakvom prijenosu ne dolazi do rezanja. Podsjetimo se, pri rezanju se sva proširenja izvedene klase gube (to uključuje i zaobiđene metode). Općenito vrijedi: pri prijenosu preko pokazivača ili reference ne dolazi do rezanja. Kao posljedica tog pravila, iz funkcije IspisPov se poziva "prava" metoda povrsina. Pri prvom pozivu, riječ je o metodi povrsina klase Kvadrat, dok je pri drugom pozivu riječ o metodi povrsina klase Krug. Ključna riječ virtual u baznoj klasi Lik ovdje ima jako važnu ulogu. Da metoda povrsina u klasi Lik nije bila deklarirana kao virtual tada bi se iz funkcije IspisPov uvijek pozivala metoda povrsina klase Lik.

Ovakva hijerarhija se može jednostavno proširiti. Dovoljno je iz klase Lik izvesti novu klasu i u njoj zaobići metodu povrsina. Funkcija IspisPov automatski radi i za novo napisanu klasu.

Važno je napomenuti da funkcija IspisPov može pozvati samo one metode koje su deklarirane u klasi Lik. Ukoliko izvedena klasa sadrži nove metode (koje nisu deklarirane u klasi Lik), metoda IspisPov ih preko pokazivača pLik ne može pozvati. Uloga klase Lik u ovom slučaju je da deklarira metode koje su zajedničke za sve klase u hijerarhiji. Izvedene klase mogu (ali i ne moraju) zaobići te metode. Sada možemo navesti i opća pravila pri pisanju virtualnih metoda:

1. Bazna klasa deklarira metode koje su zajedničke za cijelu hijerarhiju (npr. metoda za računanje površine). Metode koje su namijenjene za zaobilaženje u izvedenim klasama se moraju deklarirati kao virtualne.

2. Izvedena klasa može zaobići neke od metoda bazne klase. Za svoje lokalne potrebe izvedena klasa može dodati nove metode i podatkovne članove.

3. Određeni dijelovi programa (funkcije ili metode) barataju sa pokazivačem ili referencom na baznu klasu. Preko tog pokazivača (ili reference) mogu se pozvati metode koje su deklarirane u baznoj klasi. Metode koje nisu deklarirane u baznoj klasi se preko tog pokazivača (ili reference) ne mogu pozvati.

4. Pri pozivu funkcije ili metode iz točke 3. moguće je poslati pokazivač ili referencu na bilo koji objekt izvedene klase. Ukoliko je metoda u baznoj klasi deklarirana kao virtualna pozvati će se "prava" metoda. To ovisi o tome koji pokazivač (ili referenca) je zapravo proslijeđen funkciji.

Page 10: 6.1 Naslijeđivanje

ČISTE VIRTUALNE FUNKCIJE

U prethodnom primjeru metoda povrsina u baznoj klasi je uvijek vraćala nula. Pri deklaraciji virtualne funkcije nije potrebno definirati funkciju:

class Lik{ public:

virtual float povrsina() = 0;};

Kaže se da je metoda povrsina u klasi Lik deklarirana kao čista virtualna funkcija. Kao posljedica toga, nije dozvoljeno stvoriti novi objekt klase Lik:

Lik gl; // pogrešno jer Lik sadrži čistu virtualnu funkciju

Ovime se zapravo označava da je klasa predviđena za daljnje naslijeđivanje. Programer mora izvesti novu klasu i zaobići čistu virtualnu funkciju (tj. napisati definiciju za . Općenito vrijedi da se objekt neke klase smije stvoriti samo ukoliko ta klasa ne sadrži niti jednu čistu virtualnu funkciju. Svojstvo čiste virtualne funkcije se gubi u izvedenoj klasi ukoliko se metoda zaobiđe. Slijedećih par linija koda ilustrira što je sve dozvoljeno, a što je pogrešno za klasu Lik sa čistom virtualnom funkcijom povrsina i ranije napisanu klasu Kvadrat koja zaobilazi tu funkciju:

Lik gl; // pogrešno jer Lik sadrži čistu virtualnu funkciju

Kvadrat x; // ispravno jer Kvadrat ne sadrži čistu virtualnu // funkciju

Lik *pLik; // ispravno jer se ne stvara novi objekt

pLik = new Lik; // pogrešno jer se stvara novi objekt klase Lik

pLik = new Kvadrat; // ispravno jer se stvara novi objekt klase // Kvadrat

Koja je svrha svega ovoga? Bazna klasa mora definirati ono što je zajedničko za sve objekte u hijerarhiji. Metode koje se moraju zaobići u izvedenim klasama se deklariraju kao čiste virtualne funkcije, metode koje se mogu (ali i ne moraju) zaobići se deklariraju kao virtualne funkcije. Ukoliko bazna klasa sadrži čiste virtualne funkcije tada se objekt bazne klase ne može stvoriti. S druge strane, preko pokazivača ili reference na baznu klasu moguće je pozivati sve metode koje su deklarirane u baznoj klasi.

Page 11: 6.1 Naslijeđivanje

NASLIJEĐIVANJE.................................................................................................................................1

JEDNOSTAVNO JEDNOSTRUKO NASLIJEĐIVANJE............................................................1SINTAKSA NASLIJEĐIVANJA...........................................................................................1JAVNO NASLIJEĐIVANJE.................................................................................................1

POZIVI KONSTRUKTORA I DESTRUKTORA U IZVEDENOJ KLASI.................................3PROSLIJEĐIVANJE ARGUMENATA KONSTRUKTORU BAZNE KLASE......................4

ZAOBILAŽENJE METODA BAZNE KLASE............................................................................5GRAĐENJE OSNOVNE HIJERARHIJE......................................................................................7

KOMPATIBILNOST KLASA...............................................................................................7VIRTUALNE METODE................................................................................................................8

ČISTE VIRTUALNE FUNKCIJE....................................................................................10