[ Kurt2 @ 24.04.2006. 20:14 ] @
Problem broj jedan:

Code:

#include <iostream.h>
#include <stdlib.h>
#include <string.h>

class Student;

class Person {
public:
    Person() {cout << "constructor Person" << endl;}
    ~Person() {cout<< "destructor Person" << endl;}
};

const Student& returnPerson(const Student& p) {return p;}

class Student : public Person {
public:
    Student() {cout << "constructor Student" << endl;}
    ~Student() {cout << "destructor Student" << endl;}

};

Student returnStudent(Student s) {return s;}

class PhDStudent: public Student {
public:
    PhDStudent(){cout << "constructor PhDStudent" << endl;}
    ~PhDStudent() {cout << "destructor PhDStudent" << endl;}
};

Student returnPhDStudent(Student s)
{
    return s;
}

int main(int argc, char* argv[])
{
    for (int i=0; i<10; i++)
        cout << endl;
    PhDStudent laza;
    cout << endl;
    returnPhDStudent(returnStudent(returnPerson(laza)));
    cout << endl;
}


Rezultat u konzoli:

constructor Person
constructor Student
constructor PhDStudent

destructor Student
destructor Person
destructor Student
destructor Person
destructor Student
destructor Person

destructor PhDStudent
destructor Student
destructor Person

Prva tri konstruktora i poslednja tri destruktora su jasni. Ali: Zašto šest destruktora, bez ijednog konstruktora?

const Student& returnPerson(const Student& p) {return p;} - Šta ampersendi (tj. referenciranje) menja u pogledu izvršavanja konstruktora?

Problem broj dva:

Code:

#include <iostream.h>

class Klasa {
public:
    Klasa() {cout << "Konstruktor klase Klasa \n";}
    ~Klasa() {cout << "Destruktor klase Klasa \n";}
};

class Osnovna {
public:
    Osnovna() {cout << "Konstruktor osnovne klase \n" << endl;}
    ~Osnovna() {cout << "Destruktor osnovne klase \n" << endl;}
};

class Izvedena : public Osnovna {
private:
    Klasa x;
public:
    Izvedena() {cout << "Konstruktor izvedene klase" << endl;;}
    ~Izvedena() {cout << "Destruktor izvedene klase" << endl;}
};

void main()
{
    Izvedena d;
}


Zašto se konstruktori izvršavaju redosledom: Osnovna, Klasa pa tek onda Izvedena? Zar nije logičnije da ide konstruktor osnovne, pa onda izvedene, pa tek na kraju klase Klasa?

Problem broj tri:

Code:

#include <iostream.h>

class Osnovna {
public:
    virtual void f() {
        cout << "Funkcija OSNOVNE klase \n";
        }
};
class Izvedena : public Osnovna {
public:
    void f() {
        cout << "Funkcija IZVEDENE klase \n";
        }
};

void g1(Osnovna b) {b.f();}
void g2(Osnovna *pb) {pb->f();}
void g3(Osnovna &rb) {rb.f();}

void main()
{
 for (int i=0;i<10; i++)
    cout << endl;
 Izvedena d;

 g1(d);                                                  //1. poziva se Osnovna::f()
 g2(&d);                                                //2. poziva se Izvedena::f()
 g3(d);                                                  //3. poziva se Izvedena::f()
 cout << endl;
 Osnovna *pb = new Izvedena; pb->f();     //4. poziva se Izvedena::f()
 Osnovna &rb=d; rb.f();                           //5. poziva se Izvedena::f()  
 Osnovna b=d; b.f();                               //6. poziva se Osnovna::f()
 delete pb; pb=&b; pb->f();                     //7. poziva se Osnovna::f()
}


Šta mu dođe &rb=d?
Poslednji red: pb je pokazivač tipa Osnovna, ono našta pokazuje se briše, i onda pokazuje na b koji opet pokazuje (ili je možda ispravnije reći je isto što i?) na d. Zašto se onda poziva Osnovna::f()?

Hvala na vremenu! ;)
[ NrmMyth @ 24.04.2006. 21:52 ] @
ja se uvijek prepadnem kad vidim toliki post.
[ tupito @ 24.04.2006. 22:00 ] @
kod prvog slucaja ti masina poziva ne onaj konstructor koji si ti definisao nego copy constructor pa zato ti nista ne ispiuje , ovo ti je copy konstraktor:
Code:

class Klasa{
       Klasa( const Klasa& r){};
}


ukoliko napises funkciju :

Klasa get(Klasa k){return k;}

masina poziva copy constructor i ustvari u ovo malo koda imas cetiri objekta :
1. objekat k koji dajes funkciji
2. objekat k unutar funkcije koji se dobija pomocu copy cnstructora
3. automatski objekat koji nastaje od returna (medju rezultat koji ti nevidis)
4. objekat koji prima rezultat funkcije get koji se kopira od automaskog objekta

e sad ako je kompajler malo bolji moze da izbegne u nekim slucajevima automaski objekat pod 3 i da ide iz 2 u 4;
ovo gore znaci tri poziva kostruktora sto je veoma sporo

pa kada imas sledecu funkciju :

Klasa& get(Klasa& k){return k;}

on ne kopira objekat tri puta vec samo predaje referencu objekta ali zato ako menjas objekat unutar funkcije ti menjas ustvari objekat k koji si prosledio funkciji:
1. objekat k koji prosledjujes funkciji
2. objekat koji prima rezultat

ovde ce se u najgorem slucaju pozvati samo jednom copy constructor a ako hvatas samo referencu niti jedan.

ako se pitas staje refernca to ti je kao pointer na objekat (samo sto je brze od pointera)

kod kostruktora prvo se pozivaju kostruktori oca klase pa zatim se pozivaju kanstruktori membera klase i to onim redosledom koji si ih deklarisao pa na kraju construktor same klase.

Code:

Osnovna &rb=d; // ovde ti je rb referenca na d odnosno rb i d su isti objekat
Osnovna b=d; // ovde se stvara novi objekat b koji kopija objekta d 


mislim da je to sve, nadam se da sam ti pomogao ... pozdrav








[Ovu poruku je menjao tupito dana 24.04.2006. u 23:04 GMT+1]
[ Kurt2 @ 25.04.2006. 00:29 ] @
Hvala ti, pomogao si, mada još uvek čekam odgovor na drugo pitanje.
Znači, kada pozivam funkciju kojoj prosleđujem neki objekat, poziva se copy konstruktor za taj objekat, naravno ako postoji, ako ne postoji onda ga kompajler samo pravi, pri čemu ta implementacija ne mora da baš ispadne dobra, što sada nije bitno. E sad, jel mogu ja da zaključim da se destruktor poziva jer se pre toga pozivao konstruktor specijalnog tipa (jeste da je copy, ali je ipak konstruktor)? Malo mi je nejasno pitanje, ali valjda me razumeš. Znači, radi se o tome da ja hoću da nađem razlog zašto se pozivaju ti silni destruktori. To je u ovom slučaju zbog copy konstruktora, zar ne?
P.S. Jel može neki linkovi koji se detaljnije bave virtualnim funkcijama i virtualnim nasleđivanjem, kao i virtualnim mehanizmom uopšte?
[ tupito @ 25.04.2006. 01:34 ] @
constructor Person
constructor Student
constructor PhDStudent
-------------------|
destructor Student |
destructor Person |
destructor Student |---ovo su ti pomocni objekti koje je stvorila masina i posto im je zivotni vek istekao pa ih je masina unistila
destructor Person |
destructor Student |
destructor Person |
--------------------
destructor PhDStudent
destructor Student
destructor Person


ti pomocni objekti su promenljive unutar funkcije i pomocne promenljive za medju rezultate.
Code:

class Klasa {
    MemberKlasa m_member;
   Klasa()
  { 
     m_member.funkcija( 10 ); // da bi konstruktoru tvoje klase uopste mogao da koristis membere 
                                        //tvoje klase masina mora da ih stvori
                                        //(i samim tim pozove njihov kostraktor)                                   
                                        // pre nego sto pozove tvoj konstraktor
  }

}

najbolje ti je ipak da nabavis knjigu od nasih ti preoporucujem od Dragana Miliceva Objektno orjentisano programiranje u C++
od stranih pogledaj http://www.novetehnologije.com/Default.aspx?tabid=104
[ Kurt2 @ 25.04.2006. 10:59 ] @
Ma jasno je to meni za pomoćne objekte, ali, ako ima destruktora, zašto onda nema konstruktora?
[ leka @ 26.04.2006. 09:39 ] @
Ako nema konstruktora, a potrebni su, C++ ih generise automatski.
[ yooyo @ 26.04.2006. 14:18 ] @
Mozda je malo offtopic... ali cesto se desava da se izostavi virtuelni destruktor u klasama koje imaju virtuelne funkcije. Ovo moze biti uzrok "curenja" memorije u situacijama kada izvodite novu klasu.
MSVC ima jedan interesantan switch /w34265 koji ce izbaciti warrning u situaciji kada klasa ima virtuelne funkcije, ali nema virtuelni destruktor. Dakle, dodajte /w34265 u projekat i popravite eventualna upozorenja.