[ Wajda.W @ 30.01.2007. 20:01 ] @
Code:

class A
{int i;
public:
A(int j=0):i(j){}
virtual void print()
{cout<<"i="<<i<<endl;}
void print(char *s)
{cout<<s<<i<<endl;}
};


class B:public A
{int i;
B(int j=0):A(5),i(j){}
void print()
{cout<<"i="<<i<<endl;}
int print(char *s)
{cout<<s<<i<<endl;
return i;}
};


main()
{
B b1,b2(10),*pb=&b2;
A a1,a2(10),*pa;
a1.print();
a2.print();
b1.print();
b2.print();
a1.print("a1.i=");
a2.print("a2.i=");
b1.print("b1.i=");
b2.print("b2.i=");
pa=pb;
pa->print();
pa->print("b2.i=");
pb->print();
pb->print("b2.i=");
}

Na ekranu se ispisuje sledece:
i=0
i=10
i=0
i=10
a1.i=0
a2.i=10
b1.i=0
b1.i=10
i=10
b2.i=5
i=10
b2.i=10
Sve mi je jasno sem ova dva reda tj. njihovih ispisa
Code:

pa->print();
pa->print("b2.i=");

nije mi jasno kako se za ove f-je dobija:
i=10
b2.i=5
Ima neka fora sa tipom pokazivaca i na sta sam pokazivac pokazuje al ne mogu da uklavirim
[ Mali Misha @ 30.01.2007. 21:08 ] @
Elem puno toga se dešava. Poduže je za priču ukoliko se ne zna šta te tačno interesuje, a trenutno imam manjak vremena/koncentracije, dakle izvini ako pričam nešto što već znaš.

Dakle: Ključni delovi ove priče su reč virtual i činjenica da objekti tipa B još uvek poseduju promenljive/metode iz A, na neki način.

Konkretno, imaš pokazivač pa.

Ako želiš "dve desetke"
Code:
    pa->print();
    ((B*)pa)->print("b2.i=");


Ako želiš "dve petice"
Code:
    pa->A::print();
    pa->print("b2.i=");
[ Wajda.W @ 31.01.2007. 11:32 ] @
Ne treba da promenim ispis pa da nesto drugo pise vec jednostavno da mi neko objasni ta dva dela, zasto se za poziv te f-je dobije taj rezultat.
samo toliko.
[ Mali Misha @ 01.02.2007. 06:46 ] @
Pa dobro. Prvo objekat o kojem se radi je tipa B. Tip B je nasleđivanjem A dobio sledeće osobine:

- Pošto je A-ov void print() virtual, postao je prepisan B-ovim void print(). A-ov možeš pozvati samo eksplicitno.
- Ostao mu je A-ov void print(char *s), koga možeš pozivati ukoliko je pokazivač tipa A.
- Ostao mu je A-ov i, koji se ponaša kao i void print(char *s). No on se ne može pozivati jer je private.
- Dobio je svoj i, koji može imati vrednost različitu od vrednosti A-ovog i.
- Dobio je int print(char *s), koji ima prednost na A-ovim void print(char *s) ukoliko je pokazivač tipa B. Suprotno važi.

Tako kod, pa->print(); pozivaš još uvek B-ov print() za objekat b2. Tako dobijaš 10.
Kod pa->print("b2.i="); pak pozivaš distupan A-ov pa->print("b2.i=");. Tako dobijaš 5.
[ S_3_ka @ 01.02.2007. 22:49 ] @
Pa kao prvo, pa, iako je pokazivač na objekat A, trenutno pokazuje na objekat b2, koji je instanca klase B. Ovo je moguće jer potomak uvek može da zameni svog pretka.

pa->print(); ovde se poziva metoda klase B, jer je metoda print() vitruelna metoda. Pri pozivu virtuelne metode, klasa traži adresu virtualne metode koja je pridružena svakom objektu i nalazi se u tableli virtuelnih metoda. Kako "pa" pokazuje na objekat klase B, poziva se metoda klase B.

pa->print("b2.i="); ovde se poziva metoda klase A, jer metoda print(char *s) nije virtuelna. Kako je "pa" zapravo tipa pokazivača na klasu A, adresa metode koja se poziva se ne traži u tabeli virtualnih metoda, jer nije virtuelna, već je skok na nju ugrađen.

Za razumevanje ovog koda potrebno je razumevanje koncepta virtuelnih metoda. Ukratko ću objasniti ono što koncept virtuelnih i nevirtuelnih metoda omogućava.

Recimo da imaš pokazivač na neku klasu i pozivaš neku metodu. Ako ta metoda nije virtuelna, poziva se metoda klase čijeg je pokazivač tipa, bez obzira na tip kase na koju taj pokazivač u datom momentu pokazuje. Ako je metoda vituelna, poziva se metoda klase na koju pokazivač u tom momentu pokazuje.