Presentation is loading. Please wait.

Presentation is loading. Please wait.

Изведене класе Вишеструко извођење Полиморфизам

Similar presentations


Presentation on theme: "Изведене класе Вишеструко извођење Полиморфизам"— Presentation transcript:

1 Изведене класе Вишеструко извођење Полиморфизам
Наслеђивање Изведене класе Вишеструко извођење Полиморфизам

2 Изведене класе Принцип наслеђивања реализован је концептом изведене класе. У пракси је чест случај да је нека класа B подврста друге класе A, тј. објекти класе B имају све особине као и објекти класе А али и неке додатне.

3 Изведене класе A B C Класа А је основна класа

4 Изведене класе class Base { // osnovna klasa int i; public: void f(); }; class Derived : public Base { // izvedena klasa int j; void g();

5 Изведене класе Објекти изведене класе имају све чланове које има и основна класа и још и оне наведене у декларацији изведене класе.

6 Изведене класе void main () { Base b; Derived d; b.f(); b.g(); // ovo ne moze! d.f(); // ovo moze; d ima i funkciju f d.g(); // i funkciju g }

7 Изведене класе Изведена класа не наслеђује једино:
конструкторе, деструкторе, функцију чланицу operator=. Пријатељство се такође не наслеђује!

8 ime_klase::ime_clana
Изведене класе Ако се у изведеној класи декларише члан са истим именом као у основној, онда је декларација из основне класе сакривена. Тада за приступ таквом члану морамо да наведемо име класе којој припада ime_klase::ime_clana

9 Изведене класе Класа А се назива директном основном класом неке класе B ако је наведена у листи основних класа у декларацији класе B. Ако то није случај онда се ради о индиректној основној класи.

10 Изведене класе class A { public: void f(); }; class B : public A {}; class C : public B { public: void f(); }; void C::f() { f(); // poziv f() iz C A::f(); // poziv f() iz A B::f(); // poziv f() iz A }

11 Изведене класе Кључна реч public означава јавно извођење што значи да су сви јавни чланови основне класе уједно и јавни чланови изведене класе, сви заштићени чланови основне класе уједно и заштићени чланови изведене класе, док приватни остају приватни.

12 Изведене класе class Base { int pb; public: int jb; void put(int x) {pb=x;} };

13 Изведене класе class Derived : public Base { int pd; public: void write(int a, int b, int c) { pd=a; jb=b; pb=c; // greska – ne moze ovako! put(c); // mora ovako } };

14 Изведене класе Понекад постоји потреба да члановима основне класе могу да приступају чланице изведених класа али не и корисници класа. Такви чланови треба да буду заштићени (protected).

15 Изведене класе class Base { int pb; protected: int zb; public: int jb; };

16 Изведене класе class Derived : public Base { // … public: void write(int x) { jb=zb=x; // moze se pristupiti javnom i zasticenom pb=x; // ali ne i privatnom – greska! } };

17 Изведене класе void f() { Base b; b.zb=5; // greska: ne moze se pristupiti zasticenom }

18 Изведене класе Ако у декларацији изведене класе наведемо кључну реч private (то је подразумевано) ради се о приватном извођењу што значи да сви јавни и заштићени чланови основне класе постају приватни чланови изведене класе.

19 Изведене класе Ако у декларацији изведене класе наведемо кључну реч protected ради се о заштићеном извођењу што значи да сви јавни и заштићени чланови основне класе постају заштићени чланови изведене класе.

20 Изведене класе class Base { int bpriv; protected: int bprot; public: int bpub; };

21 ime_klase::ime_clana
Изведене класе Права приступа се могу изменити у приватно изведеној класи али само до нивоа права приступа који је био у основној класи. ime_klase::ime_clana

22 Изведене класе class PrivDerived : private Base { // privatno izvodjenje protected: Base::bprot; // vracanje na nivo protected Base::bpub; // greska – smanjenje nivoa prava pristupa public: Base::bprot; // greska – povecanje nivoa prava pristupa };

23 Изведене класе Не може се променити ниво права приступа за преклопљене функције чланице које имају различита права приступа у основној класи. Не може се променити ниво права приступа за члана основне класе који има исто име као и члан изведене класе.

24 Изведене класе Пријатељи или функција чланица изведене класе могу да приступају заштићеном статичком члану основне класе. Међутим, ако се ради о заштићеном нестатичком члану, онда је то могуће само преко показивача или референце на објекат те изведене класе, или објекта изведене класе.

25 Изведене класе class B { protected: int i; }; class D1 : public B {}; class D2 : public B { friend void f(B*, D1*, D2*); void m(B*, D1*);

26 Изведене класе void f(B *pb, D1 *p1, D2 *p2) { pb->i=1; // greska! p1->i=2; // greska! p2->i=3; // u redu }; void D2::m(B *pb, D1 *p1) { i=3; // u redu, pristup preko this tipa D2 *const

27 Изведене класе Треба уочити да наслеђивање изражено релацијом „B је једна врста од А“ која није симетрична. Јавно извођење је оно које подржава принцип наслеђивања. Када је реч о приватном извођењу, оно реализује другачију релацију „А је део од B“.

28 Изведене класе Кажемо за основну класу да је доступна на неком месту у програму ако су доступни јавни чланови те класе. У вези са овим је и правило да се показивач на изведену класу може конвертовати у показивач на доступну основну класу.

29 Изведене класе class Base {/* … */); class PrDerived : private Base {}; class PubDerived : public Base {}; void main () { PrDerived prd; Base *pb1=&prd; // greska: PrDerived* se ne moze // konvertovati u Base* PubDerived pbd; Base *pb2=&pbd; // u redu: osnovna klasa je dostupna }

30 Изведене класе Слично је и са референцама: референца на изведену класу може се конвертовати у референцу на доступну основну класу. Конверзија објекта изведене класе у објекат основне класе није дефинисана али није ни потребна, јер се објекат доступне основне класе може иницијализовати објектом изведене класе.

31 Изведене класе class Base {/* … */); class Derived : public Base {/* … */}; void main () { Derived d; Base b=d; // u redu: d je u isto vreme i tipa Base }

32 Изведене класе За објекат изведене класе сматра се да је истовремено и типа доступне основне класе. Стога је приликом иницијализације објекта b позван конструктор копије основне класе са формалним аргументом (const) Base&. Референца Derived& може се имплицитно конвертовати у Base&.

33 Изведене класе Исто важи и за друге случајеве иницијализације.
class Base {/* … */); class Derived : public Base {/* … */}; extern void f(Base); void main () { Derived d; f(d); // u redu: d je u isto vreme i tipa Base }

34 Изведене класе Слично је и за операцију доделе: објекат изведене класе може се доделити објекту доступне основне класе, али не и обрнуто. Derived d; Base b; b=d // u redu: d se odseca na podobjekat tipa Base d=b // greska!

35 Изведене класе Приликом креирања објекта изведене класе позива се њен конструктор али и конструктор основне класе. У заглављу дефиниције конструктора изведене класе, у листи иницијализатора, може се навести и иницијализатор директне основне класе.

36 Изведене класе class Base { int bi; // … public: Base(int); // konstruktor osnovne klase }; Base::Base (int i) : bi(i) {/* … */}

37 Изведене класе class Derived : public Base { int di; // … public: Derived(int); }; Derived::Derived (int i) : Base(i), di(i+1) {/* … */} // inicijalizatori osnovne klase Base i clana di

38 Изведене класе Када се креира објекат изведене класе најпре се бира конструктор те класе који ће се позвати, али се пре извршења тела тог конструктора позива конструктор основне класе који најбоље одговара стварним аргументима у иницијализатору. Овај конструктор иницијализује подобјекат основне класе у оквиру објекта изведене класе.

39 Изведене класе Затим се иницијализују чланови изведене класе, у редоследу у коме су декларисани. Тек онда се извршава тело конструктора изведене класе. Када се објекат укида, редослед је обрнут.

40 Изведене класе #include <iostream.h> class X { // … public: X() {cout<<“Konstruktor klase X.\n”;} ~X() {cout<<“Destruktor klase X.\n”;} };

41 Изведене класе class Base { // … public: Base() {cout<<“Konstruktor osnovne klase.\n”;} ~Base() {cout<<“Destruktor osnovne klase.\n”;} };

42 Изведене класе class Derived : public Base { X x; // … public: Derived() {cout<<“Konstruktor izvedene klase.\n”;} ~Derived() {cout<<“Destruktor izvedene klase.\n”;} };

43 Изведене класе void main () { Derived d; } /* izlaz:
Konstruktor osnovne klase. Konstruktor klase X. Konstruktor izvedene klase. Destruktor izvedene klase. Destruktor klase X. Destruktor osnovne klase. */

44 Изведене класе Објекти класе се реализују као структуре података које садрже само податке чланове. Функције чланице се реализују као обичне функције са скривеним аргументом this који указује на структуру података које је објекат.

45 Изведене класе class A { int a; public: void f(); }; int a;

46 Редослед није гарантован језиком – зависи од преводиоца!
Изведене класе class B : public A { int b; public: void g(); }; class C : private B { int c; void h(); int a; int b; int c; Редослед није гарантован језиком – зависи од преводиоца!

47 Вишеструко извођење Понекад постоји потреба да изведена класа има особине више основних класа истовремено. Тада се ради о вишеструком наслеђивању. C B A

48 Вишеструко извођење class Derived : public Base1, public Base 2, private Base 3 { // … };

49 Вишеструко извођење Ако је нека класа X вишеструка индиректна основна класа класе C, онда ће објекти класе C имати вишеструке чланове класе X, односно имаће више подобјеката класе X унутар једног објекта класе C.

50 Вишеструко извођење class X { public: int i; }; class A : public X {}; class B : public X {}; class C : public A, public B { public: void f();

51 Вишеструко извођење Објекти класе C има ће два члана са именом i, и у сваком од објеката биће два подобјекта типа X, један наслеђен од A други наслеђен од B. Приликом приступа члану i мора се навести име класе којој припада.

52 Вишеструко извођење void C::f() { i=0; // greska: dvosmislenost, A::i ili B::i A::i=B::i; // ovako moze } C B A X

53 class C : public B, public B {}; // greska
Вишеструко извођење Није дозвољено да једна класа буде вишеструка директна основна класа. class C : public B, public B {}; // greska

54 Вишеструко извођење Конверзија показивача или референце на изведену класу у показивач или референцу на основну класу, дозвољена је само ако је основна класа доступна и ако је конверзија недвосмислена.

55 Вишеструко извођење C *pc=new C; X *px1=pc; // greska: dvosmisleno X *px2=(X*)pc; // greska: i dalje je dvosmisleno X *px3=(X*) (A*)pc; // ok, px3 ukazuje na X iz podobjekta A X *px3=(X*) (B*)pc; // ok, px3 ukazuje na X iz podobjekta B

56 Вишеструко извођење Ако је потребно да изведена класа има само један подобјекат индиректне основне класе, онда ту основну класу треба декларисати као виртуелну. class X {*/ … */}; class A : virtual public X {*/ … */}; class B : virtual public X {*/ … */}; class C : public A, public B{*/ … */}; C B A X

57 Вишеструко извођење Класа може да има и виртуелне и невиртуелне индиректне основне класе. class X {*/ … */}; class A : virtual public X {*/ … */}; class B : virtual public X {*/ … */}; class C : public X {*/ … */}; class Z : public A, public B, public C, public X{*/ … */};

58 Вишеструко извођење У овом случају објекат класе Z има три подобјекта типа X: један заједнички за подобјекте A и B, један одвојен унутар подобјекта C и један сопствени за објекат Z. Z B A X C

59 Вишеструко извођење Када нека класа Z има виртуелну основну класу X, преводилац обезбеђује кад год се негде појављује објекат типа Z, било као самосталан или подобјекат неке изведене класе, да се проналази неки подобјекат X наслеђен као виртуелан, да би га овај објекат Z делио са другима.

60 Вишеструко извођење class X {*/ … */}; class Y : virtual public X {*/ … */}; class Z : public Y, virtual public X{*/ … */}; Овде ће објекат класе Z имати само један подобјекат класе X.

61 Вишеструко извођење Као и код једноструког извођења, вишеструке основне класе се иницијализују навођењем иницијализатора у заглављу конструктора изведене класе. Овако се може вршити иницијализација на само са директним основним класама. Виртуелне основне класе су посебан случај.

62 Вишеструко извођење class A { public: A(int); }; class B { public: B(int); class X : public A, public B { public: X(int i) : A(i+1), B(i+2) {/* … */}

63 Вишеструко извођење class V { public: V(int); }; class A : virtual public V { public: A(int i) : V(i) {/* … */} class B : virtual public V { B(int i) : V(i) {/* … */}

64 Вишеструко извођење class X : public A, public B, private virtual V { public: X(int i) : A(i), B(i), V(i) {/* … */} };

65 Полиморфизам Полиморфизам је својство да објекат извршава операцију на начин својствен изведеној класи којој припада, иако му се приступа као примерку основне класе. Нпр., имамо класу figura која реализује геометријске фигуре са чланицом crtaj () и из ње изведене класе krug, kvadrat, trougao.

66 Полиморфизам void crtanje () { for (int i=0; i<broj_figura; i++) niz_figura[i]->crtaj(); // niz pokazivaca na funkcije }

67 Полиморфизам Функције чланице основне класе које се у изведеним класама могу реализовати специфично за сваку изведену класу називају се виртуелним функцијама. Нека имамо класу clan_biblioteke са потребним подацима и операцију плаћања чланарине.

68 Полиморфизам Нека је из ове класе изведена pocasni_clan али се таквим члановима наплаћује мања чланарина.

69 Полиморфизам class clan_biblioteke { // … protected: racun r; public: virtual int plati_clanarinu () // virtuelna funkcija { return r-=clanarina; } };

70 Полиморфизам class pocasni_clan: public clan_biblioteke { // … public: int plati_clanarinu () { return r; } // nova verzija funkcije };

71 Полиморфизам void naplata_clanarine () { extern clan_biblioteke *clanovi[]; // niz clanova biblioteke // … for (int i=0; i<broj_clanova; i++) ispis(clanovi[i]->plati_clanarinu ()); }

72 Полиморфизам Ако се тип функције декларисане у изведеној класи разликује од типа виртуелне функције са истим именом у основној класи, онда функција у изведеној класи сакрива функцију основне класе. Није дозвољено да се ове функције разликују само по типу резултата.

73 Полиморфизам Кључна реч virtual може али и не мора да се наведе у декларацији нове верзије виртуелне функције у изведеној класи.

74 Полиморфизам class B { public: virtual void vf1(); virtual void vf2(); virtual void vf3(); void f(); }

75 Полиморфизам class D : public B { public: void vf1(); // nova verzija void vf2(int); // sakriva B::vf2; int vf3(); // greska: razlika samo po tipu rezultata void f(); // ovo nije virtuelna funkcija }

76 Полиморфизам Позив виртуелне функције разрешава се према објекту на који указује показивач или упућује референца а не према типу показивача (референце). Позив невиртуелне функције се разрешава у односу на тип показивача (референце) а не у односу на тип објекта на који указује.

77 Полиморфизам Изведена класа може али и не мора да редефинише виртуелну функцију основне класе (тада се позива функција основне класе). Виртуелна функција не може да буде глобална функција нечланица и не може да буде статичка, али може да буде пријатељ неке друге класе.

78 Полиморфизам Експлицитни позив функције са квалификатором ime_klase::ime_funkcije не активира виртуелни механизам.

79 Полиморфизам class B { // … public: virtual void f(); };

80 Полиморфизам class D : public B { // … public: void f() { B::f(); // poziv osnovne verzije // … // uradi jos nesto } };

81 Полиморфизам Показивач на објекте изведене класе може се имплицитно конвертовати у показивач на објекат доступне основне класе. Последица је да се показивачу на објекат основне класе директно може доделити показивач на објекте изведене класе. Истовремено то значи и могућност иницијализације ПООК помоћу ПОИК.

82 Полиморфизам Показивач на основну класу B може се само експлицитно конвертовати у показивач на изведену класу D, ако је B директна или индиректна основна класа класе D и B није виртуелна основна класа класе D. Резултат је коректан само ако је је објекат на који показује полазни показивач подобјекат типа B унутар објекта типа D.

83 Полиморфизам Када се позива виртуелна функција за објекат познатог типа, нема потребе да се активира виртуелни механизам. Када се тип објекта не зна на месту позива (случај када се објекту приступа преко показивача/референце), активира се виртуелни механизам.

84 Полиморфизам У овом случају се одлука о томе која се функција позива доноси у време извршавања позива. Овакав механизам разрешавања позива назива се динамичко везивање.

85 Полиморфизам class Base { // … public: virtual void f(); }; class Derived : public Base { void f();

86 Полиморфизам void g1(Base b) { b.f(); } void g2(Base *pb) { pb->f(); void g3(Base &rb) { rb.f();

87 Полиморфизам void main () { Derived d; g1(d); // poziva se Base::f g2(&d); // poziva se Derived::f g3(d); // poziva se Derived::f Base *pb=new Derived; // konverzija iz Derived* u Base* pb->f(); // poziva se Derived::f Base &rb=d; // konverzija iz Derived& u Base& rb.f(); // poziva se Derived::f Base b=d; b.f(); // poziva se Base::f; delete pb; pb=&b; pb->f(); // poziva se Base::f }

88 Полиморфизам Концепт виртуелних основних класа и виртуелних функција нису повезани. Ипак, постоји заједничка особина. Код виртуелних основних класа помињање имена неког члана у програму може се одности на више различитих функција, објеката или константи типа набрајања.

89 Полиморфизам class V { public: void f(); int x; }; class B : public virtual V {

90 Полиморфизам class D : public B, public virtual V { public: void g() { x++; // na koje x se odnosi? f(); // na koje f se odnosi? } }; D V(f,x) B(f,x)

91 Полиморфизам Овакви случајеви решавају се правилом доминације.
Име D::f у општем случају доминира над именом B::f ако је B основна класа класе D.

92 Полиморфизам Контрола права приступа виртуелној функцији врши се у складу са њеном декларацијом и на та права не утичу правила везана за функције које је касније редефинишу.

93 Полиморфизам class B { public: virtual void f(); // virtuelna funkcija f }; class D : public B { private: void f(); // redefinisana funkcija f

94 Полиморфизам void main () { D d; B *pb=&d; D *pd=&d; pb->f(); // u redu: B::f je javna a poziva se D::f pd->f(); // greska: D::f je privatna }

95 Полиморфизам Унутар конструктора и деструктора могу се позивати функције чланице а то важи и за виртуелне фунцкије. У таквом случају позива се она верзија виртуелне функције која припада класи чији је то конструктор а не редефинисана верзија у изведеним класама.

96 Полиморфизам class B { public: virtual void f(); // virtuelna funkcija f B() { f(); } // poziva se uvek B::f ~B() { f(); } // poziva se uvek B::f }; class D : public B { int &r; void f() { r++; } // redefinisana virtuelna funkcija D(int &rr) : r(rr) {}

97 Полиморфизам void main () { int i=0; D d(i); };

98 Полиморфизам И деструктор може да буде виртуелан.

99 Полиморфизам class Base { // … public: virtual ~B(); // virtuelni destruktor }; class Derived : public Base { ~Derived(); // destruktor je virtuelan //…

100 Полиморфизам void release (Base *pb) { delete pb; } // poziv virtuelnog destruktora void main () { Base *pb=new Base; Derived *pd=new Derived; release(pb); // poziva se ~Base(); release(pd); // poziva se ~Derived(); }

101 Полиморфизам Правило је да ако основна класа има неку виртуелну функцију требало би да и њен деструктор (ако постоји) буде виртуелан. Унутар виртуелног деструктора изведене класе не треба експлицитно позивати деструктор основне класе.

102 Полиморфизам Већ је речено да је објекат изведене класе једна врста објекта основне класе. Међутим, низ објеката изведене класе није једна врста низа објеката основне класе. Зато, ако се употребљава наслеђивање, треба користити низ показивача на објекте.

103 Полиморфизам class Base { public: int bi; }; class Derived : public Base { public: int di; // destruktor je virtuelan

104 Полиморфизам void f(Base *b) { cout<<b[2].bi; } void main () { Derived d[5]; d[2].bi=77; f(d); // Derived[] se konvertuje u Derived* // a zatim u Base*; nece se ispisati 77 }

105 Полиморфизам void f(Base **b, int i) { cout<<b[i]->bi; } void main () { Base b1,b2; Derived d1,d2,d3; Base *b[5]; // b je tipa Base*[] b[0]=&d1; b[1]=&b1; b[2]=&d2; // konverzije Derived* u // Base* b[3]=&d3; b[4]=&b2; d2.bi=77; f(b,2); // ispisace se 77 }

106 Полиморфизам void main () { Derived *d[5]; // d se moze konvertovati u tip Derived** // … f(d,2); // nije dozvoljena konverzija Derived** u // Base** }

107 Полиморфизам Понекад класа нема ниједан примерак већ служи да се из ње изведу класе. У том случају ради се о апстрактној класи. Апстрактна класа мора да има бар једну виртуелну функцију која је у њој декларисана али није и дефинисана. Таква виртуелна функција назива се чистом виртуелном функцијом.

108 Полиморфизам class OutCahrDevice { // … public: virtual OutStatus put (char) = 0; // cista virtuelna funkcija };


Download ppt "Изведене класе Вишеструко извођење Полиморфизам"

Similar presentations


Ads by Google