Constructori si destructori



    Initializarea datelor
    La declararea datelor de tip predefinit sau definit de utilizator prin structuri sau clase, compilatorul aloca o zona de memorie corespunzatoare tipului respectiv. Este indicat ca în cazul în care datele structurate au ca membrii pointeri, sa se aloce memorie în mod dinamic.

    În general, datele numerice (globale) au valori implicite; sunt initializate automat cu valoarea 0 iar cele de tip sir de caractere cu sirul vid.. Initializarea datelor simple de tip predefinit se poate realiza dupa declararea acestora, sau în momentul declararii.
Exemple:
int i;  i=30;//declararea variabilei i, apoi initializarea ei prin atribuire
char c='A'; //declararea si initializarea variabilei c
    Initializarea datelor structurate se poate realiza în momentul declararii acestora, prin listele de initializare.
Exemple:
//1
int a[]={20, 30, 40, 50};  //declararea si initializarea vectorului a
//2
double m[2][3]={{1.1,2.2,3.3}, {11.11,22.22,33.33}};//declararea si initializarea matricii m
//3
struct pers{
 char nume[20]; int varsta; double salariu;
}p={"Popescu", 20, 8000000};

·        Constructori
Constructorii sunt metode speciale care folosesc la crearea si initializarea instantelor unei clase.

·        Programatorul poate defini un constructor.

·        In absenta altor definitii, clasei i se ataseaza in mod implicit un constructor. Un astfel de constructor se numeste constructor implicit.

·        Constructorii impliciti nu au parametri

·        Constructorii impliciti nu se genereaza in cazul in care clasa are atasat un alt constructor  (asadar constructorii impliciti sunt constructori fara parametri generati automat de limbaj daca programatorul nu si-a definit unul).

·        Constructorii au acelasi nume ca si clasa careia îi apartin

·        Constructorii sunt apelati de fiecare data când se creaza noi instante ale clasei.

class complex

{public:

 float x,y,m; //datele clasei

 void display();//metodele clasei

 float modul();};

 

float complex::modul()

{return sqrt(x*x+y*y);

}

void complex::display()
{cout<<x<<"+"<<y<<"*i";}

Clasa nu are definit un constructor prin urmare este generat in mod automat un constructor implicit care va permite declararea unor instante ale clasei astfel:

void main()
{ complex q1; //constructorul implicit permite instantiarea clasei complex
  complex *q=new complex;
  cout<<q1.x<<” „<<q1.y; //afiseaza valori reziduale
  cout<<endl<<q->x<<” „<<q->y; //afiseaza valori reziduale

……………..
}

Cum am mai spus, programatorul isi poate defini constructori proprii. Constructorii vor fi definiti ca niste functii fara tip, fara a se trece in dreptul constructorului cuvantul cheie void. Constructorul va avea acelasi nume ca si al clasei careia ii apartine.

O clasa poate avea mai multi constructori, care difera între ei prin numarul si tipul parametrilor acestora. Acest lucru este posibil deoarece limbajul C++ permite supradefinirea ( supraincarcarea=overloading) functiilor.

Supraîncarcarea (supradefinirea) reprezinta posibilitatea de a atribui unui nume mai multe semnificatii, care sunt selectate în functie de context. Practic, se pot defini functii cu acelasi nume, dar cu liste de parametri diferite, ca numar si/sau ca tipuri de parametri. În momentul apelului functiei, selectarea functiei adecvate se face în urma compararii tipurilor parametrilor efectivi cu tipurile parametrilor formali. De aceea, declararea unor functii cu acelasi nume si acelasi set de parametri este ilegala si este semnalata ca eroare la compilare.

    La întâlnirea declararii unui obiect, se apeleaza automat un constructor al clasei respective. La fiecare instantiere a clasei se aloca memorie pentru datele membre. Deci pentru fiecare obiect declarat se aloca memorie pentru datele membre ale clasei. Functiile membru exista într-un singur exemplar pentru toate instantele clasei.

Ordinea în care sunt apelati constructorii corespunde ordinii declararii obiectelor.

    Proprietatile constructorilor:

Exemple de costructori definiti de catre programator:

Ex1

#include<math.h>

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

 float x,y,m; //datele clasei

 void display();

 float modul(); //metoda clasei

 complex()                        //constructor fara parametri definit de catre programator

    {cout<<endl<<"mesaj de la constructor"<<endl;}

 };

 

float complex::modul()

{return sqrt(x*x+y*y);

}

 

void complex::display()

{cout<<x<<"+"<<y<<"*i";}

 

complex q;

 

void main()

{complex q1,q2;

 getch();

 clrscr();

}

Testand programul anterior veti observa ca se afiseaza pe ecran de trei ori mesajul: mesaj de la constructor,  corespunzator fiecarei declarari a celor trei instante ale clasei complex.
   

Urmatorul exemplu contine in plus  inca un constructor definit de catre programator, constructor ce are un parametru.

Ex2

#include<math.h>

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

  float x,y,m; //datele clasei

  void display();

  float modul(); //metoda clasei

  complex()

    {cout<<endl<<"mesaj de la constructor"<<endl;}

 

  complex(float yy);

 };

 

complex::complex(float xx)

 {x=xx;

 y=0;

 }

 

float complex::modul()

{return sqrt(x*x+y*y);

}

 

void complex::display()

{cout<<endl<<x<<"+"<<y<<"*i";

cout<<endl;

}

 

complex q;

 

void main()

{cout<<"Obiectul global q=";

q.display();

complex q1;

cout<<"Obiectul local q1, retine valori reziduale";

q1.display();

complex q2(6.7); //se apleleaza constructorul cu un parametru

q2.display();

 

getch();

clrscr();

}

Urmatorul exemplu permite prin intermediul mecanismului de supraincarcare definirea unui constructor cu doi parametri:

Ex3

#include<math.h>

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

  float x,y,m; //datele clasei

  void display();

  float modul(); //metoda clasei

  complex()

  {cout<<endl<<"mesaj de la constructor"<<endl;}

 

  complex(float yy);

  complex(float xx, float yy);

 };

 

complex::complex(float xx)

 {x=xx;

 y=0;

 }

 

complex::complex(float xx, float yy)

 {x=xx; y=yy;

 }

 

float complex::modul()

{return sqrt(x*x+y*y);

}

 

void complex::display()

{cout<<endl<<x<<"+"<<y<<"*i";

cout<<endl;

}

 

complex q;

 

void main()

{cout<<"Obiectul global q=";

q.display();

complex q1;

cout<<"Obiectul local q1, retine valori reziduale";

q1.display();

complex q2(6.7);

cout<<"q2=";

q2.display();

complex q3(1.2,1.3);

cout<<"q3=";

q3.display();

getch();

clrscr();

}

Ca orice alta functie în limbajul C++, constructorii pot avea parametri impliciti , fiind numiti constructori cu parametri impliciti. Varianta constructorului cu parametri impliciti poate fi adoptata în toate cazurile în care constructorul nu necesita argumente. Daca toti parametrii unui constructor sunt impliciti, apelul constructorului are forma unei simple declaratii . Constructorii pot fi apelati si în mod explicit . În cazul în care dorim sa instantiem obiecte atât initializate, cât si neinitializate se poate folosi un constructor implicit vid, care se va apela la instantierea obiectelor neinitializate .

Exemplul 4:  Pentru clasa complex s-a definit un constructor cu parametri impliciti; din acest motiv s-a putut face declaratia "complex q;" 

// varianta constructor cu parametri impliciti

// permite declarare de instante de tip complex fara parametri, cu un parametru sau doi

//foarte flexibil

#include<math.h>

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

  float x,y,m; //datele clasei

  void display();

  float modul(); //metoda clasei

 

  complex(float xx=0, float yy=0)

   {cout<<endl<<"mesaj de la constructorul cu parametri impliciti "<<endl;

    x=xx;

    y=yy;

   }

 };

 

float complex::modul()

{return sqrt(x*x+y*y);

}

 

void complex::display()

{cout<<endl<<x<<"+"<<y<<"*i";

cout<<endl;

}

 

complex q; //obiect neinitializat ; apelul nu se face in mod explicit

 

void main()

{cout<<"Obiectul global q=";

q.display();

complex q1; //obiect neinitializat ; apelul nu se face in mod explicit

cout<<"Obiectul local q1 ";

q1.display();

complex q2(6.7); // obiect initializatt.

cout<<"q2=";

q2.display();

complex q3(1.2,1.3); // obiect initializat.

cout<<"q3=";

q3.display();

complex q4=complex();  // constructorul este apelat în mod explicit.

q4.display();

getch();

clrscr();

}

La apelul explicit al constructorului: complex q4=complex() evaluarea expresiei complex() conduce la:
- Crearea unui obiect temporar de tip complex (obiect cu o adresa precisa,  dar inaccesibil);
- Apelul constructorului pentru acest obiect temporar;
- Copierea acestui obiect temporar în q4.

    Constructori de copiere
Daca programatorul nu defineste un constructor de copiere, compilatorul genereaza un asemenea constructor, implicit.

Pentru o clasa, se poate defini un contructor de copiere, care sa permita copierea obiectelor. Deoarece parametrii unui constructor nu pot fi de tipul definit de clasa al carei membru este, ci o referinta la acesta, constructorul de copiere pentru clasa nume_clasa, are, de obicei, prototipul:

                nume_clasa (nume_clasa & ob);

Parametrul transmis prin referinta este obiectul a carui copiere se realizeaza

Exemplul 5:

#include<math.h>

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

  float x,y,m; //datele clasei

  void display();

 

  float modul(); //metoda clasei

 

  complex(float xx=0, float yy=0)

   {cout<<endl<<"mesaj de la constructorul cu parametri impliciti "<<endl;

    x=xx;

    y=yy;

   }

 

   complex(complex &ob)              //constructor de copiere

     { cout<<endl<<"operatie de copiere ";

      x=ob.x;

      y=ob.y;

     }

 };

 

float complex::modul()

{return sqrt(x*x+y*y);

}

 

void complex::display()

{cout<<endl<<x<<"+"<<y<<"*i";

cout<<endl;

}

 

void main()

{complex q1(1.2,1.3);

cout<<"q1=";

q1.display();

complex q2=q1; //se apeleaza constructorul de copiere

cout<<"q2=";

q2.display();

complex q3=complex(q1); //se apeleaza constructorul de copiere

 

cout<<"q3=";

q3.display();

getch();

clrscr();

}

    Destructori
    Destructorii sunt metode ale claselor care actioneaza în sens invers, complementar, fata de constructori. Constructorii sunt folositi pentru alocarea memoriei, initializarea datelor membru sau alte operatii (cum ar fi, incrementarea unui contor pentru instantele clasei). Constructorul este apelat în momentul declararii obiectelor.
Destructorul elibereaza memoria alocata de constructori. Destructorul este apelat automat, la iesirea din blocul în care este recunoscut acel obiect.

    Proprietatile destructorilor

Exemplu 6:

#include<math.h>

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

  float x,y,m; //datele clasei

  void display();

 

  float modul(); //metoda clasei

 

  complex(float xx=0, float yy=0)

   {cout<<endl<<"mesaj de la constructorul cu parametri impliciti "<<endl;

    x=xx;

    y=yy;

   }

 

   complex(complex &ob)

     { cout<<endl<<"operatie de copiere ";

      x=ob.x;

      y=ob.y;

     }

 

 ~complex ()

    {cout<<endl<<"am apelat destructorul pentru"<<endl;  //destructor

    display();}

 };

 

float complex::modul()

{return sqrt(x*x+y*y);

}

 

void complex::display()

{cout<<endl<<x<<"+"<<y<<"*i";

cout<<endl;

}

 

void main()

{complex q1(1.1,1.1);

cout<<"q1=";

q1.display();

complex q2(2.2,2.2);

cout<<"q2=";

q2.display();

complex q3(3.3,3.3);

cout<<"q3=";

q3.display();

// getch();

}

    Exercitiu:
    Sa se defineasca tipul punct, cu datele membre x si y, reprezentând abscisa si ordonata unui punct. Operatiile care pot fi realizate asupra obiectelor de tip punct, sunt: afisare (afiseaza coordonatele unui punct), deplasare (deplaseaza un punct, noile coordonate ale punctului fiind obtinute prin adunarea unor valori transmise ca parametri, la valorile anterioare ale coordonatelor), abscisa (returneaza valoarea abscisei), ordonata (returneaza valoarea ordonatei). Se vor implementa, deasemenea, constructor cu parametri impliciti, constructor având ca parametri valorile abscisei si a ordonatei, constructor de copiere si destructor.
    Sa se defineasca tipul segment, cu datele membre A si B, de tip punct, reprezentând capetele unui segment (originea si vârful). Operatiile care pot fi realizate asupra obiectelor de tip segment, sunt: afisare (afiseaza coordonatele capetellor segmentului), deplasare (translateaza un segment, deplasând capetele acestuia cu valorile transmise ca parametri), origine (returneaza originea segmentului), vârf (returneaza vârful segmentului). Se vor implementa, deasemenea, constructor, constructor de copiere si destructor.
Sa se testeze tipurile de date punct si segment.
 

#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
//CLASA PUNCT
class punct
{ double x,y;
public:
 punct()
{x=0;y=0;cout<<"Constr. implicit pentru punct("<<x<<","<<y<<")\n";}
//constructor initializare
punct(double,double);
punct(punct&);   //constructor copiere
~punct();    //destructor
double abscisa(){return x;}
double ordonata(){return y;}
 void afisare();
void deplasare(double,double);
};

//CLASA SEGMENT
class segment
{private:
 punct A,B;
 public:
 segment(punct&,punct&);  //constructor
 segment(segment&);  //constructor copiere
 ~segment();    //destructor
 punct origine();
 punct varf();
 void afisare();
 void translatie(double,double);
};

//METODELE CLASEI PUNCT
punct::punct(double valx,double valy)
{ x=valx;y=valy; cout<<"Constructor punct ("<<x<<","<<y<<")\n"; }
punct::~punct()
{cout<<"Destructor punct ("<<x<<","<<y<<")\n";}
punct::punct( punct &P)
{ x=P.x;y=P.y; cout<<"Constructor copiere pct ("<<x<<","<<y<<")\n";}
void punct::deplasare(double dx,double dy)
{x+=dx; y+=dy;}
void punct::afisare()
{ cout<<"Punct ("<<x<<','<<y<<')';}

//METODELE CLASEI SEGMENT
segment::segment(punct &A1,punct &B1)
{ A=A1;B=B1;cout<<"Constructor segment[";A.afisare();B.afisare();
cout<<"]\n";}
segment::segment(segment &AB)
{ A=AB.A; B=AB.B; cout<<"Constructor copiere segment [";
A.afisare(); B.afisare();cout<<"]\n";}
punct segment::origine()
{ return A;}
punct segment::varf()
{ return B;}
void segment::afisare()
{ cout<<"[";A.afisare();cout<<','; B.afisare();cout<<"]"<<'\n'; }
segment::~segment()
{ cout<<"Destructor segment [";A.afisare(); cout<<",";B.afisare();
cout<<"]\n";}
void segment::translatie(double dx,double dy)
{ A.deplasare(dx,dy); B.deplasare(dx,dy);}

void main()
{clrscr();
punct P(7.8,-20.4),Q(-4.82,8.897),A,B;
/*Constructor punct (7.8,-20.4) (Pentru punctul P)
Constructor punct (-4.82,8.897) (Pentru punctul Q)
Constr. implicit pentru punct(0,0)
Constr. implicit pentru punct(0,0) (pentru punctele A, B)*/
punct P3, Q3;
// Constr. implicit pentru punct(0,0)Constr. implicit pentru punct(0,0) (pentru punctele P3, Q3)
segment S(P,Q);
/* Constr. implicit pentru punct(0,0)Constr. implicit pentru punct(0,0)
(pentru membrii A, B ai obiectului S, deci pentru S.A si S.B)
Constructor segment[Punct (7.8,-20.4)Punct (-4.82,8.897)] (pentru obiectul S, de tip segment) */
segment S1(P3,Q3);
/* Constr. implicit pentru punct(0,0)
Constr. implicit pentru punct(0,0) (pentru membrii A, B ai obiectului S1, deci pentru S1.A si S1.B)
Constructor segment[Punct (0,0)Punct (0,0)] (pentru obiectul S1, de tip segment) */
printf("Apasa un car. ptr. continuare!\n");  getch();
cout<<"Punctele:\n";
P.afisare();cout<<'\n';  Q.afisare();cout<<'\n';
P3.afisare();cout<<'\n'; Q3.afisare();cout<<'\n';
A.afisare(); cout<<'\n'; B.afisare();cout<<'\n';
cout<<"\nSegment:"; S.afisare(); cout<<'\n';
/* Punctele:
Punct (7.8,-20.4) (pentru obiectul P)
Punct (-4.82,8.897) (pentru obiectul Q)
Punct (0,0) (pentru obiectul A)
Punct (0,0) (pentru obiectul B)
Punct (0,0) (pentru obiectul P3)
Punct (0,0) (pentru obiectul Q3)
Segment:[Punct (7.8,-20.4),Punct (-4.82,8.897)] */
punct D(1,2); punct C;
// Constructor punct (1,2)Constr. implicit pentru punct(0,0) (pentru punctele D, C)
C=D;   //operatie de atribuire
C.afisare(); // Punct (1,2) (pentru punctul C)
getch();
punct CC=C;  // Constructor copiere pct (1,2)
cout<<"In urma copierii:"; CC.afisare();
// În urma copierii:Punct (1,2) (pentru punctul CC)
cout<<"Se deplaseaza punctul CC cu valorile 10, 20. Noile coord.=";
CC.deplasare(10, 20); CC.afisare();
// Se deplaseaza punctul CC cu valorile 10, 20. Noile coord.=Punct (11,22)
cout<<"Abscisa CC="<<CC.abscisa()<<" Ordonata CC="<<CC.ordonata()<<'\n';
//Abscisa CC=11 Ordonata CC=22
cout<<"Varf segment S="; (S.varf()).afisare();
// Varf segment S=Constructor copiere pct (-4.82,8.897) (metoda varf returneaza un punct, copiere)
// Punct (-4.82, 8.897)
//Destructor punct (-4.82,8.897)
cout<<"Origine segment S="; CC=S.origine();
/* Origine segment S=Constructor copiere pct (7.8,-20.4) (metoda origine returneaza un punct, copiere) Destructor punct (7.8,-20.4) */
CC.afisare();  // Punct (-4.82, 8.897)
S1=S;   //operatie de atribuire
S1.afisare();
// Punct (7.8,-20.4)[Punct (7.8,-20.4),Punct (-4.82,8.897)]
cout<<"Translatie S1 cu 100,1000. S1 translatat este:";
S1.translatie(100, 1000); S1.afisare();
// Translatie S1 cu 100,1000. S1 translatat este:[Punct (107.8,979.6),Punct (95.18,1008.897)]
segment S2=S1; /* Constr. implicit pentru punct(0,0) (pentru S2.A)
Constr. implicit pentru punct(0,0) (pentru S2.B)
Constructor copiere segment [Punct (107.8,979.6)Punct (95.18,1008.897)]
Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)]*/
cout<<"Segment S2 obtinut prin copiere:";
S2.afisare(); // Segment S2 obtinut prin copiere:[Punct (107.8,979.6),Punct (95.18,1008.897)]
cout<<"Iesire din main\n"; // Iesire din main
}
/* La iesirea din functia main, deci la terminarea duratei de viata a obiectelor, se apeleaza automat destructorii, în ordinea inversa în care au fost apelati constructorii, astfel:

Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)] (pentru segmentul S2)
Destructor punct (95.18,1008.897) (pentru membrii B, respectiv A, ai segmentului S2: S2.B, apoi S2.A)
Destructor punct (107.8,979.6)
Destructor punct (7.8,-20.4) (pentru CC)
Destructor punct (1,2) (pentru C)
Destructor punct (1,2) (pentru D)
Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)] (pentru segmentul S1)
Destructor punct (95.18,1008.897) (pentru membrii B, respectiv A, ai segmentului S1: S1.B, apoi S1.A)
Destructor punct (107.8,979.6)
Destructor segment [Punct (7.8,-20.4),Punct (-4.82,8.897)] (pentru segmentul S)
Destructor punct (-4.82,8.897) (pentru membrii B, respectiv A, ai segmentului S: S.B, apoi S.A)
Destructor punct (7.8,-20.4)
Destructor punct (0,0) (pentru punctul Q3)
Destructor punct (0,0) (pentru punctul P3)
Destructor punct (0,0) (pentru punctul B)
Destructor punct (0,0) (pentru punctul A)
Destructor punct (-4.82,8.897) (pentru punctul Q)
Destructor punct (7.8,-20.4) (pentru punctul P) */

Exercitiul evidentiaza urmatoarele probleme:
1. În situatia în care o clasa C1 are ca date membre obiecte ale altei clase C2 (clasa segment are ca date membre obiecte de tipul punct), la construirea unui obiect din C1, se apeleaza întâi constructorul C2 pentru membrii (de tip C2), apoi constructorul C1.
Un astfel de exemplu îl constituie declararea  segmentului S: segment S(P,Q);
Se apeleaza întâi constructorul implicit al clasei punct pentru membrii A si B ai segmentului S (deci pentru S.A si S.B), apoi constructorul clasei segment . La distrugerea obiectului din clasa C1, destructorii sunt apelati în ordinea inversa constructorilor (întâi se apeleaza destructorul clasei segment - învelisul exterior, apoi destructorul pentru membrii de tip punct).
2. Sa revedem secventa:
punct D(1,2); punct C; C=D;
În acest caz, se realizeaza o atribuire, membru cu membru, echivalenta cu C.x=D.x si C.y=D.y.
3. Sa revedem secventa:
punct CC=C;
În acest caz, se apeleaza constructorul de copiere, care creaza punctul CC prin copierea punctului C. Apelul constructorului de copiere se poate realiza si explicit:
punct CC=punct(C);
4. Parametrii transmisi unei functii pot fi obiecte, pointeri catre obiecte sau referinte catre obiecte. Valoarea returnata de o functie poate fi un obiect, pointer catre obiect sau referinta catre obiect.

segment::segment(punct &A1,punct &B1)
{ A=A1;B=B1;cout<<"Constructor segment\n";}
Constructorul primeste ca parametri referinte catre obiecte de tipul punct. Apelul constructorului:
segment S(P, Q);
Parametrii efectivi P si Q sunt referinte pentru A1 si B1 (aceleasi obiecte). Ca urmare, se apeleaza cei doi constructori impliciti pentru membrii A si B ai segmentului S. În urma operatiei de atribuire din corpul constructorului segmentului, ei sunt initializati. Mesajele:
"Constructor pct implicit!!" (pentru membrul A al segmentului S)
"Constructor pct implicit!!" (pentru membrul B al segmentului S)
"Constructor segment"  (pentru segmentului S)

Constructorului puteau sa i se transmita parametri prin pointeri:
segment::segment(punct *A1,punct *B1)
{ A=*A1;B=*B1;cout<<"Constructor segment\n";}
Apelul:  segment S(&P, &Q);
Parametrii formali A1 si B1 sunt initializati în momentul apelului constructorului cu adresele punctelor P, respectiv Q. Situatia este similara celei anterioare, mesajele obtinute sunt identice celor obtinute în cazul transmiterii parametrilor prin referinta.

Constructorului puteau sa i se transmita parametri prin valoare:
segment::segment(punct A1,punct B1)
{ A=A1;B=B1;cout<<"Constructor segment\n";}
Apelul:  segment S(P, Q);
În aceasta situatie, la apel, pentru parametrii formali A1 si B1 se rezerva memorie pe stiva: obiectele locale constructorului, A1 si B1, sunt initializate prin copiere (la transmiterea parametrilor prin valoare, se realizeaza o copiere a parametrilor efectivi în parametrii formali). La terminarea executiei corpului functiei, punctele A1 si B1 sunt distruse. De aceea, mesajele din aceasta situatie, sunt:
"Constructor copiere punct!!"  (pentru A1, local constructorului)
"Constructor copiere punct!!"  (pentru B1, local constructorului)
"Constructor pct. implicit!!" (pentru membrul A al segmentului)
"Constructor pct. implicit!!" (pentru membrul B al segmentului)
"Constructor segment!" (pentru segmentul S)
"Destructor punct!" (pentru B1, la iesirea din constructor)
"Destructor punct!" (pentru A1, la iesirea din constructor)

Exercitiu:  Pentru tipurile punct si segment implementate anterior, sa se scrie si sa se testeze urmatorul program, în care obiectele A, B (de tip punct) si AB (de tip segment) sunt globale (declarate în afara oricarei functii). Se folosesc, deasemenea, variabile locale statice. Pentru variabilele globale (A, B, AB) si cele locale declarate explicit statice (P1 din test1, U si V din blocul interior functiei main), se aloca memorie statica. Pentru variabilele locale se aloca memorie automatic, pe stiva. Sa se urmareasca evidentieze crearea si distrugerea obiectelor statice si automatici, domeniul de vizibilitate si timpul de viata.

class punct{ //. . . . .
};

class segment
{  //. . . . .
};
//Implementarea metodelor clasei punct
//Implementarea metodelor clasei segment

punct test1()
{ cout<<"Intrare in test1\n";
static punct P1(20,10);
P1.deplasare(1,1); cout<<"Iesire din test1\n";return P1;}
punct test2()
{ punct P1(100,100);P1.deplasare(10,20);return P1; }

punct A(1,2), B;
segment AB(A, B);
void main()
{cout<<"S-a intrat in main!\n"; punct E(1, 1), F, G;
F=test1(); cout<<"F="; F.afisare();
getch();G=test2();cout<<"Intrare in test1\n";cout<<"G="; G.afisare();
 {
cout<<"Intrare in blocul interior\n";
 static punct U(5,2);punct C(9,9), D(5.5,6.6);static punct V(8,3);getch();
 F=test1(); cout<<"Intrare in test1\n";F.afisare();G=test2(); cout<<"Intrare in test2\n";G.afisare();
cout<<"Iesire din blocul interior\n";
 }
getch();A.afisare();F.afisare();AB.afisare();AB.translatie(10, 10);
cout<<"Segment translatat:"; AB.afisare();
cout<<"Segmentul AB are originea:"; (AB.origine()).afisare();
cout<<"Segmentul AB are varful:"; (AB.varf()).afisare();
cout<<"Iesire din main()\n";
}