[ Goran Arandjelovic @ 03.04.2005. 22:29 ] @
Zamolio bih za malu pomoc: Pisao sam nesto.. i pri deklarisanju destruktora sam se zapitao.. da li je moguce napisati sledece:

Code:

nekaklasa::nekaklasa()
{
    //bilo sta...
}

nekaklasa::~nekaklasa()
{
    delete this; //nejasno mi je da li ovo sme!
}


a posle sam se igrao sa sledecim kodom...
Code:

int main()
{
    nekaklasa *objekat;
    objekat=new nekaklasa;
    objekat->~nekaklasa(); //posle ovoga je hdd poceo da vrti ko zna sta... ovo je verovatno
glupo... deluje mi kao da se nesto poziva rekurzivno :(
}


dakle, sta je sve ovde neispravno i zasto i da li je moguce, pozeljno ili potrebno u nekoj
metodi klase koristiti "delete this" za brisanje datog objekta?

hvala.
[ Mihajlo Cvetanović @ 04.04.2005. 09:13 ] @
Dozvoljeno je pozivati destruktor direktno i dozvoljeno je pozivati

delete this. Nije dozvoljeno samo pozivati delete this iz destruktora.


Direktno pozivanje destruktora se koristi kad recimo hoces da

implementiras specificne new i delete operatore, recimo zbog sopstvenog

memory managera. Primer za delete this je za modeless CWnd prozor, kada

se u PostNcDestroy (poslednji metod koji se poziva pre nego sto GUI

prozor nestane sa vidika) poziva delete this da bi obrisao CWnd objekat

pridruzen GUI prozoru.
[ Goran Arandjelovic @ 04.04.2005. 13:33 ] @
da...razumeo sam donekle. medjutim, nije mi bas jasno jos uvek nesto...

this je pointer koji poseduju samo fukcije clanice date klase. da li to znaci da smem bez problema da pozivam 'delete this' u bilo kojoj funkciji klase? (koliko sam video, moze) ako je tako, u cemu je specificniji destruktor? da li on poziva nesto ili brise objekat cak i kada je prazan?
[ Mihajlo Cvetanović @ 04.04.2005. 14:49 ] @
Destruktor se poziva kad ti pozoves delete this. Mozes da ga posmatras

kao svojevrsni event handler, gde je dogadjaj "objekat se brise". U

destruktor bi recimo stavio kod kojim se na primer brise neki char* koji

je clan doticnog objekta. delete this mozes da pozoves u bilo kojoj

funkciji clanici, bilo kad, samo sto posle delete this ne smes da

pristupas clanovima objekta, niti da pozivas funkcije koje bi pristupile

clanovima objekta (jer jel"te clanova vise nema).
[ Goran Arandjelovic @ 04.04.2005. 14:56 ] @
shvatio, hvala.
[ Goran Arandjelovic @ 04.04.2005. 14:59 ] @
i ipak jeste onako kako sam mislio... u onom primeru koji sam gore naveo... destruktor se poziva rekurzivno... zato je meni kucao program...
[ X Files @ 04.04.2005. 20:15 ] @
Postoje slucajevi (doduse retki) kada se koristi i 'delete this',
uglavnom u raznoraznim Release() operacijama, ali tada se
koliko ja znam destruktor proglasava privatnim.

Npr:

// Netestirano !!!

class nekaklasa
{
public:
nekaklasa() {};
void Release() { delete this; }

private:
~nekaklasa(){};
};

i zatim:

nekaklasa*f = new nekaklasa;
f->Release();

Ali posto je ovo cudan spoj, mozes i konstruktor da napravis privatnim.
Tada mozes da napravis svoj Create() kao staticki (valjda).

class nekaklasa
{
public:
static nekaklasa* Create() { return new nekaklasa; }
void Release() { delete this;}
private:
nekaklasa() {}
~nekaklasa() {}
};

i zatim:

nekaklasa*f = nekaklasa::Create();
f->Release();


itd...
[ Goran Arandjelovic @ 06.04.2005. 15:59 ] @
Da.. to moze, medjutim ne vidim tu onda neku razliku da li ces imati poseban Create i Release ili ce to standardno obavljati konstruktor i destruktor. Valjda u svakom slucaju to 'delete this' koje se nalazi Release funkciji poziva destruktor (da li ima veze da li je privatan ili ne??).
[ Mihajlo Cvetanović @ 06.04.2005. 16:49 ] @
Ako je konstuktor privatan onda niko drugi osim same klase ne moze da

pozove "new MyClass", i analogno za destruktor i "delete pMyClass". Ako

je makar jedan od ova dva privatan onda klasa ne moze da se instancira

na steku. Kompajler implicitno konstruise operatore new i delete za

svaku klasu i oni pripadaju samoj klasi, tako da "privatnost" njima ne

smeta.
[ Goran Arandjelovic @ 06.04.2005. 17:30 ] @
Aha...razumeo. Davez sam veliki, pa bih molio da me udostojis jednog primera bas oko instanciranja klase na steku. Sta je zapravo problem, nisam u potpunosti razbistrio sta je stek a sta heap, znam da se stek npr. puni kada se poziva rekurzivna funkcija koja zapravo 'lepi' podatke jedne iznad druge i posle cita obrnutim redom... e sada, fizicki ne znam gde se to nalazi :( to je problem.
[ Mihajlo Cvetanović @ 06.04.2005. 18:12 ] @
U C++ standardu nigde se zapravo ne spominje pojam stack, tj. mozemo da zamislimo nekakav specijalan hardver sa specijalnim C++ kompajlerom u kome stek zapravo i ne postoji onako kako ga zamisljaju profesori po skolama. Svi postojeci kompajleri ipak imaju to ne�to �to se zove stek gde stoje parametri pri pozivu funkcija i lokalne promenljive. Ako u nekoj funkciji napises:
Citat:
void funkcija(void)
{
��� MyClass myObject;
}
onda je objekat na steku, ali ako napises
Citat:
void funkcija(void)
{
��� MyClass* pMyObject = new MyClass;
}
onda je objekat na heapu. Ono �to je na steku �e se automatski obrisati kad objekat izadje iz opsega vazenja (eng. scope), tj. kad dodje do odgovarajuce zatvorene viticaste zagrade }. Ono sto je na heapu ce se obrisati tek kad se pozove odgovarajuci delete.
[ X Files @ 06.04.2005. 19:54 ] @
Kada smo vec kod konstruktora/destruktora...

U C++-u se odavno koristi STL i 'pametni pokazivaci' za operacije
tipa new/delete, kada zelimo da se 'delete' SIGURNO izvrsi bez
obzira sta se desilo izmedju. U mnogim razvojnim timovima je to
opste prihvacen sledeci pristup:

// Sve je to u skladu sa RAII tehnikom, koja 'garantuje'
// da ce se destruktor *uvek* izvrsiti kada neki objekat izadje
// iz zone 'vidljivosti'.

void SomeFunction()
{
std::auto_ptr<nekaklasa> dobar_nacin( new nekaklasa() );
dobar_nacin->neki_metod();
// new dobar_nacin ce biti implicitno obrisan od strane
// auto_ptr-ovog destruktora
}


U suprotnom, losiji (ali mnogo bolji nacin od 'obicnog') je
sa try/finally. Na zalost C++ nema standardno 'finally' pa
je i njegova upotreba van standarda.

bool SomeClass:SomeMethod()
{
bool ReturnResult = true; // Optimisticno

TStrings *o1 = NULL;
TStrings *o2 = NULL;
TStrings *o3 = NULL;

try
{
try
{
// Izuzetak moze biti ovde...
o1 = new TStringList();
o1->WhatEver();

// ili ovde...
o2 = new TStringList();
o2->WhatEver();

// ili ovde...
o3 = new TStringList();
o3->WhatEver();
}
catch ( const Exception &e )
{
// u svakom slucaju markiramo da nije uspelo...
ReturnResult = false;
}
}
__finally
{
// Cistimo...
if ( o1 ) delete o1;
if ( o2 ) delete o2;
if ( o3 ) delete o3;
}

return ( ReturnResult );
}


[ Mihajlo Cvetanović @ 07.04.2005. 10:12 ] @
Naravno, tu je uvek i http://www.parashift.com/c++-faq-lite/, kojeg bi

trebalo procitati pre postavljanja pitanja po forumima, i pre

odgovaranja na ta ista pitanja (ovo se odnosi na mene :-) ).
[ X Files @ 07.04.2005. 13:46 ] @
Teoretski si u pravo u vezi citanja FAQ-a. Moderatori cak
imaju obicaj da obrisu pitanja koja su vec (negde) odgovorena.

Ja ne delim to misljenje. Kada bih ja imao vremena da procitam
*sve i svuda* jedan zivot bi mi bio malo a forumi ne bi trebalo
ni da postoje.

Ne vidim nista lose u tome da se neka jednostavna pitanja
ponovo odgovore - uz napomenu da se to moglo pronaci i u
FAQ.

Ono smo meni vise smeta je da skoro niko pre postavljanja pitanja
nije pregledao na primer:

http://groups-beta.google.com/

gde se moze pronaci *skoro sve*.
[ Goran Arandjelovic @ 08.04.2005. 10:16 ] @
Jeste malo moja greska. Nisam dovoljno procackao svuda u ovom slucaju. Mada, nekad se desi da jednostavno ne mogu da nadjem adekvatne primere vec uglavnom samo objasnjenje. :(