Citat:
Akademik: Nista mi nije jasno. FUCK!
Zasto ja moram iz klase Casopis da pozivam konstruktor klase Publikacija? Zar klasa Casopis nema svoj konstruktor Casopis?!
Citao sam da je redosled pozivanja konstruktora kod kreiranja objekta izvedene klase takav da se prvo poziva konstruktor osnovne klase, a potom kons. izvedene.
Medjutim, taj proces mi nije bas najjasniji.
Recimo da klasa Publikacija ima sledece atribute: id i naslov, a klasa Casopis pored ovih atributa i neke njoj svojstvene atribute: atr1 i atr2.
Ja bi htjeo recimo, da mi kons. klase Publikacija inicijalizuje atribute id i naslov, a klasa Casopis da inicijalizuje samo atr1 i atr2. Kako se to izvodi?
Kako bi ti uopste osmislio ovakav program?
Mozda je ovo oko konstruktora sve normalno i logicno, mozda sam se ja jednostavno navikao na C, pa sad ovo nikako da shvatim...
Moraš da pozoveš i konstruktor klase Publikacija zato što se
instanca (objekat) klase Casopis sastoji i iz podobjekta Publikacija i iz podobjekta Casopis... i taj objekat u memoriji (uprošćeno) izgleda tačno kao na
slici.
Možeš ti na tu instancu da pokazuješ i pokazivačem tipa Publikacija i pokazivačem tipa Casopis, ali je to instanca Casopisa...
Ako pokazuješ na objekat pokazivačem tipa Publikacija tada dolaze do izražaja virtualne funkcije. Probaj recimo da pozivaš dole pc1->NekaMetoda() i pc2->NekaMetoda i skloni "virtual" da vidiš šta se tačno dešava.
Objekat
Evo ga jedan scenario:
Code:
#include <iostream>
using namespace std;
class Publikacija
{
public:
Publikacija()
{
this->attr1 = 10;
this->attr2 = 15;
}
Publikacija(int x, int y)
{
this->attr1 = x;
this->attr2 = y;
}
virtual void NekaMetoda()
{
cout << this->attr1 << endl;
cout << this->attr2 << endl;
}
virtual ~Publikacija()
{
cout << "Destruktor: Publikacija" << endl;
}
private:
int attr1;
int attr2;
};
class Casopis : public Publikacija
{
public:
/* Jeste da se ovde ne vidi, ali se ovde prvo poziva podrazumevani konstruktor klase Publikacija: Publikacija() */
Casopis()
{
this->attr3 = 3;
this->attr4 = 7;
}
/* Možeš i da izostaviš pozivanje ovog konstruktora Publikacija koji inicijalizuje attr1 i attr2
ali onda MORA da postoji podrazumevani konstruktor Publikacija() */
Casopis(int a, int b, int c, int d) : Publikacija(a, c)
{
this->attr3 = b;
this->attr4 = d;
}
Casopis(int a, int b) : Publikacija(a+b, a-b)
{
this->attr3 = a;
this->attr4 = b;
}
virtual void NekaMetoda()
{
cout << this->attr3 << endl;
cout << this->attr4 << endl;
}
virtual ~Casopis()
{
cout << "Desktruktor: Casopis" << endl;
}
private:
int attr3;
int attr4;
};
int main()
{
Publikacija *p1 = new Publikacija();
Publikacija *p2 = new Publikacija(22, 33);
Casopis *c1 = new Casopis();
Casopis *c2 = new Casopis(10, 20, 30, 40);
Casopis *c3 = new Casopis(66, 77);
Publikacija *pc1 = new Casopis(88, 99);
Publikacija *pc2 = new Casopis();
/* itd... */
p1->NekaMetoda(); // testiraj pozivanjem ove metode i vidi šta se ispisuje
/* itd... */
/* Zbog ovoga MORAŠ da imaš virtualni destruktor */
delete p1;
delete c2; // da nemaš virtualni destruktor, obrisao bi samo deo objekta koji odgovara klasi Casopis (vidi sliku!)
delete c3;
delete c1;
delete p2;
delete pc2; // opet, da nemaš recimo virtualni destruktor, obrisao bi samo deo objekta koji odgovara klasi Publikacija
delete pc1;
return(0);
}
Recimo ovde:
Code:
Casopis(int a, int b, int c, int d) : Publikacija(a, c)
Mogao si da izostaviš pozivanje konstruktora klase Publikacija, ali bi morao da postoji podrazumevani konstruktor Publikacija().
Ako nisi sam napisao podrazumevani konstruktor Publikacija(), on se sam generiše sa praznim telom
samo ako ne postoji ni jedan drugi konstruktor u klasi Publikacija.
Dakle, konstruktori... prvo se pozivaju konstruktori baznih klasa pa onda izvedenih... a kod destruktora (virtualnih) je to obratno. A i vidiš zašto moraš da imaš virtualne destruktore. To je za početak dobra i poželjna praksa. Naravno, ove klase nisu kompletne, ali odgovaraju tvom pitanju.
[Ovu poruku je menjao Goran Arandjelovic dana 07.08.2009. u 22:48 GMT+1]