Cesto tokom cpp kodiranja naletim na situacije koje resim ali ostanem ubedjen da postoji elegantnije resenje - i naravno mrzi me da ga potrazim, a posle i zaboravim dok ne naletim opet na istu.
Pa evo danas sam naleteo na dve/tri, i reko' da pokrenem temu koja bi se bavila problemcicima na margini cpp-a za koje svi znamo resenja ali ne nuzno i elegantna.
1.) Kada imamo na primer dve polimorfne funkcije od kojih jedna kao parametar prima int a druga pointer na neki nas objekat, ili obe primaju pointere na razlicite objekte, npr:
void Bu(int nParametar);
void Bu(Pravac * pPravac);
void Bu(Neshto * pNeshto);
kako onda pozivamo zeljenu funkciju ako zelimo da joj prosledimo NULL pointer? :)
Koja ce biti pozvana od ove tri, ako pravilo postoji?
2.) Kojim redosledom objekti umiru kada izadju iz scope-a?
Npr //class A{}; class B{};
void main()
{
A a; B b;
}
Dal' prvo umire a ili b? U VC6.0 kompajleru prvo se poziva konstruktor onog koji je poslednji kreiran.
Ovako ne izgleda preterano bitna stvar ali cini mi se da je primer jednog konkretnog problema sledeci (ne garantujem, pricam napamet, secam se konkretnog problema ali tad o ovome nisam razmisljao a mrzi me da dignem vs da proverim ;) )
{
CDC MemDC;
CBitmap Bitmapa;
... bla bla inicijalizacije ...
MemDC.SelectObject(&Bitmapa)
... bla bla poso ...
}
u ovom momentu prvo umire bitmapa pa onda MemDC sa postojecim pointerom na bitmapu koja ne postoji, a moguce je da u destruktoru radi nesto sa istom jer kod kolko se secam puca ako se ne sacuva stara i vrati na kraju tj:
CBitmap * pOld = MemDC.SelectObject(&Bitmapa);
... bla bla ...
MemDC.SelectObject(pOld);
Postoji li neka specifikacija koja govori tacno o tom redosledu?
E da, i ako imamo vise cpp fajlova i globalne promenljive (objekte) u istima, kojim se redosledom inicijalizuju?
3.) Ovo moram da ilustrujem:
.h
class Problem ()
{
static int s_nLastID;
int m_nID;
Podaci m_Podatkovi;
Problem()
{
m_nID = ++s_nLastID; // inicijalizacija
}
Problem(const Problem & p)
{
<inicijalizacija>;
*this = p;
}
Problem & operator = (const Problem & eq)
{
m_Podatkovi = eq.m_Podatkovi;
return *this;
}
};
.cpp
int Problem::s_nLastID = 0;
Znaci rec je o klasi koja prilikom instanciranja markira svakom objektu unique m_nID a ostale podatke ili ne dira (default) ili kopira.
E sad, na mestu <inicijalizacija>; moze stajati kod iz (default, ako se tako zove?) konstruktora ili oba konstruktora mogu pozivati neku nasu funkciju Initialize() ili Construct().
U ovom primeru to nije problem - inicijalizacija je duga jedan red, ali ako je duga 10tak redova i postoje 3 copy konstruktora onda je jedino resenje pravljenje Construct() funkcije sto je opet malo ruznjikavo.
Pitanje je dal' postoji nacin da se iz copy konstruktora prvo pozove kod iz default konstruktora ili mora da se pravi odvojena funkcija?
Da,
Problem(const Problem & p)
{
Problem();
*this = p;
}
ne radi poso, i izaziva s***** ako se pretpostavi da radi, kao sto sam ja pretpostavio i smarao se par sati dok se nisam lupio po chelu i setio (obrnutim redom) da red Problem(); trenutno kreira objekat tog tipa a ne poziva kod za trenutni...
Nadam se da nisam smorio :)
Pa evo danas sam naleteo na dve/tri, i reko' da pokrenem temu koja bi se bavila problemcicima na margini cpp-a za koje svi znamo resenja ali ne nuzno i elegantna.
1.) Kada imamo na primer dve polimorfne funkcije od kojih jedna kao parametar prima int a druga pointer na neki nas objekat, ili obe primaju pointere na razlicite objekte, npr:
void Bu(int nParametar);
void Bu(Pravac * pPravac);
void Bu(Neshto * pNeshto);
kako onda pozivamo zeljenu funkciju ako zelimo da joj prosledimo NULL pointer? :)
Koja ce biti pozvana od ove tri, ako pravilo postoji?
2.) Kojim redosledom objekti umiru kada izadju iz scope-a?
Npr //class A{}; class B{};
void main()
{
A a; B b;
}
Dal' prvo umire a ili b? U VC6.0 kompajleru prvo se poziva konstruktor onog koji je poslednji kreiran.
Ovako ne izgleda preterano bitna stvar ali cini mi se da je primer jednog konkretnog problema sledeci (ne garantujem, pricam napamet, secam se konkretnog problema ali tad o ovome nisam razmisljao a mrzi me da dignem vs da proverim ;) )
{
CDC MemDC;
CBitmap Bitmapa;
... bla bla inicijalizacije ...
MemDC.SelectObject(&Bitmapa)
... bla bla poso ...
}
u ovom momentu prvo umire bitmapa pa onda MemDC sa postojecim pointerom na bitmapu koja ne postoji, a moguce je da u destruktoru radi nesto sa istom jer kod kolko se secam puca ako se ne sacuva stara i vrati na kraju tj:
CBitmap * pOld = MemDC.SelectObject(&Bitmapa);
... bla bla ...
MemDC.SelectObject(pOld);
Postoji li neka specifikacija koja govori tacno o tom redosledu?
E da, i ako imamo vise cpp fajlova i globalne promenljive (objekte) u istima, kojim se redosledom inicijalizuju?
3.) Ovo moram da ilustrujem:
.h
class Problem ()
{
static int s_nLastID;
int m_nID;
Podaci m_Podatkovi;
Problem()
{
m_nID = ++s_nLastID; // inicijalizacija
}
Problem(const Problem & p)
{
<inicijalizacija>;
*this = p;
}
Problem & operator = (const Problem & eq)
{
m_Podatkovi = eq.m_Podatkovi;
return *this;
}
};
.cpp
int Problem::s_nLastID = 0;
Znaci rec je o klasi koja prilikom instanciranja markira svakom objektu unique m_nID a ostale podatke ili ne dira (default) ili kopira.
E sad, na mestu <inicijalizacija>; moze stajati kod iz (default, ako se tako zove?) konstruktora ili oba konstruktora mogu pozivati neku nasu funkciju Initialize() ili Construct().
U ovom primeru to nije problem - inicijalizacija je duga jedan red, ali ako je duga 10tak redova i postoje 3 copy konstruktora onda je jedino resenje pravljenje Construct() funkcije sto je opet malo ruznjikavo.
Pitanje je dal' postoji nacin da se iz copy konstruktora prvo pozove kod iz default konstruktora ili mora da se pravi odvojena funkcija?
Da,
Problem(const Problem & p)
{
Problem();
*this = p;
}
ne radi poso, i izaziva s***** ako se pretpostavi da radi, kao sto sam ja pretpostavio i smarao se par sati dok se nisam lupio po chelu i setio (obrnutim redom) da red Problem(); trenutno kreira objekat tog tipa a ne poziva kod za trenutni...
Nadam se da nisam smorio :)