Crearea, iniţializarea şi distrugerea obiectelor unei clase
Informatica :: IT :: C++
Pagina 1 din 1
Crearea, iniţializarea şi distrugerea obiectelor unei clase
• Reamintim, ca odata cu implementarea unui tip de date, este posibila definirea unor variabile de acest tip. O variabila, avand ca tip o clasa definita de utilizator, este un obiect. Datele membre ale unei clase pot fi arbitrare, dar nu obiecte ale clasei respective. In particular, datele membre pot fi obiecte ale unei alte clase.
• Obiectele trebuie sa fie initializate. Initializarea lor se poate realiza:
a) cu ajutorul listelor de initializare
Exemplu:
struct fisier
{
FILE *fp;
char *nume;
int lung_art;
};
fisier fd={stdin,"file.bin",80}; //initializare corecta
fisier hd={stdout};
//initializare corecta,restul membrilor luand in mod implicit valoarea 0
In lista de initializare nu se accepta mai multe valori decat numarul campurilor prezente in struct.
Exemplu:
class fisier
{
public:
FILE *fp;
char *nume;
int lung_art;
};
fisier fd={stdin,"file.bin",80}; //initializare corecta
Sa observam ca, in class, initializarea variabilei fd se poate realiza, numai daca membrii clasei sunt declarati in sectiunea public. In plus, pentru astfel de obiecte, nu vor exista constructori, functii virtuale, nu pot proveni din clase derivate [aceste concepte vor fi precizate pe parcurs].
b) cu ajutorul constructorilor.
Obiectele se pot initializa in momentul instantierii (creerii) lor. In acest sens se utilizeaza unele functii membre speciale ale clasei numite constructori.
• Constructorii sunt utili in:
-initializarea obiectelor;
-alocarea dinamica de memorie;
-deschideri de fisiere etc.
• Constructorul este o functie membra a unei clase care se apeleaza automat la crearea fiecarui obiect, inclusiv pentru obiecte temporare, si se identifica cu acelasi nume ca si clasa din care face parte.
• Functia constructor nu contine tip de valoare returnata (nu retuneaza nici o valoare) si nu poate fi functie virtuala [vezi L9].
• Ca orice functie membra, un constructor admite mai multe prototipuri. Listele de parametri ale diferitelor variante de implementare trebuie sa fie diferite pentru a putea sa fie identificate corect de catre compilator.
• Parametrii unui constructor pot fi de orice tip, cu exceptia tipului definit de clasa ce contine acest constructor. Unii dintre acesti parametri pot fi pointeri sau referinte la o instanta a clasei respective.
Exemplu:
class A
{
……………..
A(A a); // incorect
…………………..
A(A*a); // corect, parametrul este un pointer la tipul definit prin clasa A
…………………….
A(A& a); // corect, parametrul este o referinta la un obiect al clasei A
}
• Un constructor poate fi:
a) implicit
- fara parametri (definit de utilizator) care poate contine in corpul sau orice fel de instructiuni valide. Un constructor „inline“ nu poate contine instructiuni cu caracter repetitiv.
- generat de compilator (cand nu exista constructori definiti de utilizator in clasa respectiva). Corpul unui astfel de constructor nu contine nici o instructiune.
b) cu parametri care iau valori in mod implicit
c) cu parametri care nu iau valori implicite
d) cu conversie de tip
e) de copiere
- definit de utilizator
- generat implicit de compilator
• La initializare, daca in clasa respectiva exista mai multi constructori, se va tine cont, la apelul lor, de lista de parametri (numarul si tipul lor) solicitata de instantierea respectiva. Daca exista un singur constructor, atunci se aplica aceleasi reguli ca la apelul functiilor din limbajul C. Ca atare, tipurile parametrilor efectivi (expresiile care vor produce initializarea) se vor converti la tipurile parametrilor formali corespunzatori ai constructorului.
• Transmiterea parametrilor actuali catre functia constructor, utili pentru initializarea unui obiect, se realizeaza in momentul creerii acestuia.
ident_clasa ident_obiect (lista);
Lista contine una sau mai multe expresii separate prin virgula. Daca nu se produce o initializare a obiectului, lista si parantezele lipsesc.
Exemplu:
class data_c{
int zi,luna,an;
public:
// initializare, constructor fara parametri (implicit)
data_c( )
{
zi=15;
luna=1;
an=1999;
}
//initializare, constructor cu parametri tip int, ultimul cu valoare implicita
data_c(int z, int l, int a=1999)
{
zi=z;
luna=l;
an=a;
}
//initializare, constructor care contine ca param. denumirea lunii
data_c(int z, char*den_l, int a);
………………..
};
Exemple de instantieri ale clasei data_c.
1) data_c d1; se apeleaza constructorul fara parametri si se obtine pentru obiectul d1: zi=15,luna=1,an=1999.
2) data_c d2(12,4,1999); se apeleaza constructorul cu toti parametri de tip int si se obtine pentru obiectul d2: zi=12, luna=4, an=1999.
3) data_c d3(12,4); se apeleaza acelasi constructor ca la d2 obtinand acelasi rezultat.
4) data_c d4(18, "ianuarie", 1999); se apeleaza ultimul constructor si se obtine pentru obiectul d4: zi=18, luna=ianuarie, an=1999.
5) data_c *pd=new data_c(18,1); se apeleaza constructorul la fel ca pentru obiectele d2 si d3 in vederea initializarii, in plus, se va realiza si o alocare de memorie heap pentru obiectul creat, iar pd are ca valoare adresa de inceput a zonei alocate obiectului respectiv.
• Datele membre ale unui obiect (de durata locala sau dinamica) daca nu au fost initializate, vor primi valori necontrolabile (imprevizibile).
• Daca intr-o clasa este prezent un constructor implicit, atunci nu se mai poate defini pentru clasa respectiva un constructor cu toti parametrii impliciti, pentru ca s-ar produce ambiguitati la instantierea obiectelor.
• Prezenta constructorilor intr-o clasa nu este obligatorie, deoarece compilatorul C++ genereaza in mod automat un constructor fara parametri (constructor implicit), care are rolul doar de alocare pentru instanta respectiva.
• Spre deosebire de alte functii membre ale unei clase, adresa unui constructor nu se poate determina.
• Constructorii definiti de programator sunt necesari atunci cand se doreste initializarea obiectelor odata cu crearea lor. Daca o clasa are cel putin un constructor si nici unul dintre ei nu este implicit, atunci nu se pot instantia obiecte neinitializate, deoarece compilatorul nu genereaza constructor implicit intr-o astfel de situatie.
Exemplu:
class complex {
double real;
double imag;
public:
complex(double x, double y)
//initializarea se realizeaza prin asignari
{
real=x;
imag=y;
}
………………
};
Se pot instantia numai obiecte de tip complex cu ambii membri initializati.
Exemplu:
complex z(4,-2);
complex u; // este incorect pentru ca nu exista constructor implicit.
• Intr-un constructor pot fi apelate si alte functii care pot fi, sau nu, functii membre ale clasei respective.
Exemplu:
class Pers{
private:
char nume[25];
long salariu;
public:
Pers(char *,long); // constructor cu parametri neimpliciti
long Sal( ) {return salariu;} //functie membra
};
Pers::Pers(char*n,long l){
strcpy(nume,n); // functie ne-membra a clasei Pers
salariu=l;
}
• Constructorul garanteaza initializarea corecta a obiectului inainte de utilizarea efectiva a sa. El ofera o garantie, in plus, asupra faptului, ca initializarea unui obiect se va efectua o singura data.
• Apelul constructorului se realizeaza in momentul declararii unui obiect.
Exemplu:
Pers p=Pers("Goga",1987345);
sau
Pers p("Goga",1987345);
• Daca un constructor are un singur parametru, initializarea se realizeaza in mod obisnuit.
Exemplu:
# include <iostream.h>
class U
{
int k;
public:
U(int c){k=c;} //constructor cu un singur parametru
int afis() {return k;}
};
main( )
{
U ob=23; // se transmite valoarea 23 lui c
cout <<ob.afis( ); // se afiseaza 23
return 0;
}
• Un constructor poate avea toti parametrii cu valori implicite.
Exemplu:
class Pers{
private:
char nume[23];
long salariu;
public:
//constructor care are parametrii cu valori implicite
Pers(char*p="Nume", long s=1987345);
………………………………………….
};
Pers::Pers(char*n,long s)
{
strcpy(nume,n);
salariu=s;
}
• Valorile parametrilor impliciti sunt prezente in declaratia constructorului si nu in cadrul implementarii sale. Apelul unui astfel de constructor se poate realiza sub una din urmatoarele forme:
Pers p1;
Pers p2("Goga");
Pers p3("Goga",1987345);
Pers p4=Pers( );
• Varianta constructorului cu parametrii ce iau valori implicite se poate folosi atunci cand constructorul nu necesita argumente (parametri efectivi) si el se va identifica cu un constructor implicit. Apelul sau se va face sub forma unei simple declaratii.
• In mod normal, constructorii se afla in zona „public“, mai rar in sectiunea "private". Daca un constructor este declarat in sectiunea „private“, el poate fi apelat doar de o alta functie membra sau functie friend. Prin urmare, numai functiile membre si friend pot crea obiecte avand constructori privati. O astfel de clasa se mai numeste si clasa privata.
• Declaratia obiectelor a caror lista de initializare se reduce la un parametru se poate scrie intr-un format asemanator cu cel de la initializarea variabilelor simple.
ident_clasa ident_obiect = expresie;
In aceasta situatie se apeleaza un constructor in care primul parametru ia ca valoare, valoarea "expresie" iar ceilalti parametri, daca exista, au valori implicite.
Exemplu:
# include <iostream.h>
class complex
{
double real;
double imag;
public:
complex(double x, double y=10)
{
real=x;
imag=y;
}
void afis( );
};
void complex::afis( )
{ if (imag<0)
cout<<real<<imag<<"*i\n";
else
cout<<real<<"+"<<imag<<"*i\n";
}
void main ( )
{ double r=3.2;
complex z1(2.56);
z1.afis();
complex z2=3*r-1;// se atribuie o expresie obiectului z2
z2.afis( );
complex z3(18.5,-9);
z3.afis( );
}
• Daca se doreste a se instantia obiecte atat initializate cat si neinitializate atunci se va folosi un constructor implicit (fara parametri), care va fi apelat la instantierea obiectelor neinitializate.
• Pentru a nu se ajunge la obiecte, care nu se pot identifica si deci initializa, nu trebuie apelat un constructor in interiorul unui alt constructor.
• In cazul in care o clasa are obiecte membre, care au constructori, acestia se apeleaza inainte de a se apela constructorul clasei respective.
• Constructorii cu conversie de tip au primul parametru de tip diferit de cel al clasei apelante. Daca mai exista si alti parametri, ei trebuie sa aiba valori implicite.
Exemplu:
class pers
{
........................
public:
pers(char*nume, long s=1987345)
............................
}
main( )
{
....................
pers t=”Horia”; // se converteste char* la pers
...................
}
• Constructorul de copiere este un constructor special care permite copierea de obiecte. Prin prezenta lui se renunta la copierea pe biti. El are ca prim parametru o referinta catre clasa din care face parte ca functie membra, iar daca mai exista si alti parametri, acestia iau valori in mod implicit.
Sintaxa:
id_clasa (const id_clasa &…);
El este util doar pentru initializari.
• Un constructor poate fi apelat explicit in situatii de genul urmator:
id_clasa ob= id_clasa (lista par_actuali);
In acest caz este apelat constructorul clasei “id_clasa” pentru a creea un obiect anonoim care va fi copiat in ob.
Exemplu:
# include <iostream.h>
class complex
{
double real;
double imag;
public:
complex(double x=10, double y=10)
{
real=x;
imag=y;
}
complex(const complex &u) // constructor de copiere
{
real=u.real;
imag=u.imag;
}
void afis( );
};
void complex::afis( )
{ if (imag<0)
cout<<real<<imag<<"*i\n";
else
cout<<real<<"+"<<imag<<"*i\n";
}
void main ( )
{
complex z1(2.56,101.99);
z1.afis();
complex z2=z1;// se aplica constructorul de copiere
z2.afis( );
complex z3(z1); // idem
z3.afis( );
//crearea unui obiect anonim care este copiat in z
complex z=complex(1.2,3.5);
z.afis( );
}
Exemplu:
class tablou_2D{
int*p;
int dim;
public:
tablou_2D(int d){
p=new int [d];
if(!p)exit(1);
dim=d;
}
~tablou_2D(){delete[]p;}
//constructor de copiere
tablou_2D(const tablou_2D &t);
void asign(int i,int j)
{
if(i>=0&&i<dim)p[i]=j;
}
int ret(int i){return p[i];
}
};
tablou_2D::tablou_2D(const tablou_2D &t)
{
int i;
p=new int [t.dim];
if(!p)exit(1);
for(i=0;i<t.dim;i++)
p[i]=t.p[i];
}
main()
{
tablou_2D X(;
int i;
for(i=0;i<8;i++)
X.asign(i,i);
for(i=7;i>=0;i--)
cout<<X.ret(i);
cout<<"\n";
tablou_2D y=X;
//se apeleaza constructorul de copiere
for(i=0;i<8;i++)
cout<<X.ret(i);
return 0;
}
• Daca se solicita un constructor de copiere si nu a fost definit de utilizator, atunci compilatorul va genera unul implicit. Elementele membre sunt copiate de la obiectul sursa la obiectul destinatie, in ordinea declararii lor in clasa.
• Initializarea elementelor membre ale unui obiect se poate face printr-un constructor care foloseste o lista de initializare.
Exemplu:
class complex{
double re,im;
public:
complex(double x, double y); // constructor - prototip
};
//lista de initializare a membrilor
complex::complex(double x, double y):re(x),im(y)
{return;}
Ordinea instantierilor este data de cea indusa prin declararea membrilor in clasa si nu de ordinea din lista de instantiere.
Exemplu:
class punct{
public:
int re,im;
punct(int x, int y){re=x; im=y;}
};
class vector {
punct varf, orig;
vector (int xv, int yv, int xo, int yo);
};
vector::vector(int xv, int yv, int xo, int yo):varf(xv,yv), orig(xo,yo)
{return;}
Ce puteti afirma despre "constructiile" de forma data mai jos si eventual, realizati secvente de program C++ in care sa le utilizati.
romb::romb(ind dl, float da)
tnod::tnod( )
arena::arena(double *x=5.0)
clasa::clasa(int u)
alfa::alfa(alfa&s)
• Daca un membru al unei clase este un pointer la o clasa, atunci nu se poate apela constructorul acelei clase in cadrul listei de instantiere.Constructorii nu pot fi apelati pentru pointeri la obiecte, ci numai pentru obiecte.
• Se accepta ca un membru al unei clase sa fie o referinta la un obiect. In acest caz referinta trebuie sa fie initializata in momentul in care este creat obiectul care contine referinta.
Exemplu:
class B
{
public:
int obs;
int &noutate;
B(int k); // constructor
};
B::B(int k):obs(k),noutate(obs); // lista de initializare
{return;}
• Membrii de tip referinta sau constanti trebuie initializati intr-o lista de instantiere. Ca atare clasele care vor avea astfel de membri, obligatoriu vor contine un constructor.
• Am vazut ca un constructor este necesar atat la initializarea unui obiect al unei clase cat si la alocarea dinamica de memorie pentru el. O alta functie membra speciala, care are rolul de a dezactiva toate functiile unui obiect creat in mod dinamic, este destructorul. Se poate spune ca destructorul distruge un obiect creat. Ca atare, destructorul este folosit in cadrul obiectului al carui constructor realizeaza o alocare dinamica de memorie. Ca si constructorii, destructorii pot efectua diverse alte operatii.
• Un destructor se identifica prin acelasi identificator ca si clasa al carei membu este, precedat de simbolul "~". Este vorba de „negarea“ unui constructor.
~iden_clasa( );
• Un destructor nu are parametri si nu contine tip de valoare returnata.
• Reamintim ca un constructor de obiecte este executat cand se intalneste instructiunea de declarare a obiectului. Daca se declara doua sau mai multe obiecte in aceeasi instructiune, constructorii sunt apelati in ordinea declararii de la stanga la dreapta.
• Functiile destructor, pentru obiecte locale, se executa in ordine inversa fata de constructorii care s-au folosit la instantiere.
• Functiile constructor pentru obiectele globale se executa inaintea functiei main(). Destructorii globali se executa in ordine inversa si dupa ce s-a incheiat functia main( ).
• Apelul destructorului se produce,in mod automat, in timpul executiei programului, cand se incheie domeniul de valabilitate (existenta) al obiectului respectiv. Nu este necesar un apel explicit al unui destructor.
• Destructorii obiectelor membre sunt apelati dupa ce destructorul obiectului principal a fost executat. Daca obiectul membru este compus din alte obiecte, atunci se va proceda la executia destructorilor obiectelor incluse.
• Daca obiectul este local unei functii, apelul destructorului se face inainte de a se iesi din functia respectiva, iar daca obiectul este static, apelul destructorului corespunzator se va face inainte de a se termina executia programului principal.
• O clasa nu poate avea mai mult de un destructor, pentru ca el nu poate fi redefinit. #n general, un destructor se declara in sectiunea public.
• La o declarare privata a unui destructor, accesul la el se poate face doar cu functii membre ale obiectului respectiv sau functii prieten (friend).
• Antetul destructorului in exteriorul clasei:
iden_clasa ::~iden_clasa( )
• Adresa unui destructor nu poate fi determinata.
Exemplu:
# include <iostream.h>
class EXE{
public:
int beta;
EXE(int par); //constructor
~EXE( ); //destructor
}ob_1(1),ob_2(2);
EXE::EXE(int par){
cout<<"AFISEAZA_INITIALIZAREA"<<par<<"\n";
beta=par;
}
EXE::~EXE( ){
cout<<"DISTRUGEREA"<<beta<<"\n";
}
main( ){
EXE ob1_local(3);
cout<<"SCRIE:\n";
EXE ob2_local(4);
return 0;}
Ce se va afisa?
Aplicatie:
Sa se realizeze un program prin care sa se afiseze un anumit numar de salariati ai unei intreprinderi impreuna cu salariile lor. Se vor utiliza constructori si destructori pentru creare, respectiv distrugere de obiecte,operatorii new si delete pentru alocare, respectiv eliberare a unei zone de memorie alocata dinamic.
#include <iostream.h>
#include<conio.h>
#include<string.h>
class persoana{
private:
char *nume;
long sal;
void init(char *s=NULL,long u=0){
nume=new char[strlen(s)+1];
strcpy(nume,s);
sal=u;
}
public:
persoana( )
{init( );}
persoana(char*s,long u)
{init(s,u);}
~persoana( )
{delete nume;}
void afis( )
{cout<<nume<<"...are salariul:"<<sal<<"tn";}
void introd(char*s,long u)
{init(s,u);}
};
class serviciu{
private:
persoana*pers;
int npers;
public:
serviciu(int n=0){
npers=n;
pers=new persoana[npers];
}
~serviciu( ){delete pers;}
void intr(int n);
void afis_1( );
};
void serviciu::intr(int n){
char s[30];
long u;
int i;
npers=n;
for(i=0;i<npers;i++){
cin>>s>>u;
pers[i].introd(s,u);
}}
void serviciu::afis_1( ){
int i;
for(i=0;i<npers;i++){
pers[i].afis( );
}
}
void main( ){
serviciu serv;
clrscr( );
serv.intr(5);
serv.afis_1( );
getch( );
}
Aplicatie:
Sa se implementeze o clasa „Stiva“ in care elementele sa fie de tip intreg. Sa se implementeze functiile membre care sa adauge cate un element in stiva, respectiv, sa extraga cate un element din stiva. O alta functie membra sa poata afisa stiva in orice moment care se doreste.
#include <iostream.h> #include <conio.h> #include <stdlib.h> class nod{ public: int cheie; nod* next;}; class Stiva{ nod*cap; public:
Stiva( ) {cap=NULL;}
~Stiva( );
int pop( );
void push(int);
void afis( );
};
void Stiva::push(int x){
nod *p;
if ((p=new nod)==NULL)
{cout<<"Memorie insuficienta!";
getch( );
exit(1);
}
p->next=cap;
p->cheie=x;
cap=p;
}
int Stiva::pop( ){
if(!cap)
{cout<<"Stiva vida";
getch( );
exit(1);
}
nod*p=cap;
int t;
t=cap->cheie;
cap=cap->next;
delete p;
return t;
}
void Stiva:: afis( ){
nod*p=cap;
while (p!=NULL)
{cout<<p->cheie;
p=p->next;
}
}
Stiva::~Stiva( ){
nod*p;
while(cap!=NULL){
p=cap;
cap=cap->next;
delete p;
}
}
void ecran( ){
clrscr( );
gotoxy(9,9);
cout<<"1:Pune";
gotoxy(9,10);
cout<<"2:Sterge";
gotoxy(9,11);
cout<<"3:Afisare";
gotoxy(9,12);
cout<<"4:Exit";
gotoxy(9,13);
}
void main ( ){
Stiva V;
int cheie;
char c;
do{
ecran( );
c=getch( );
clrscr( );
switch(c){
case'+':cout<<"Se da cheia datei care se introduce:";
cin>>cheie;
V.push(cheie);
break;
case'-':cout<<"Am extras din stiva:"<<V.pop( );
getch( ); break;
case'a':V.afis( );
getch( );
cout<<"";
break;
case'e':exit(1);
}
}while(1) ;
}
Aplicatie
Sa se defineasca un tip abstract „Lista“. Sa se implementeze o lista simplu inlantuita si cu ajutorul a doi pointeri sa se realizeze operatiile de inserare, respectiv, stergere de noduri din lista.
#include <iostream.h> #include <stdlib.h> #include <conio.h> class nod{ public: int k; nod*next;
};
class Lista{
nod*prim,*ultim;
public:
Lista();
~Lista();
void insert(nod*,int);
void elimin(int);
void afis();
};
Lista::Lista(){
char c;
nod*p_1;
prim=ultim=NULL;
do{
cout<<"tn Continuati:Y/N";
cin>>c;
if(c!='Y'&&c!='y') break;
p_1=new nod;
if(!(p_1)){
cout<<"Memorie insuficienta!";
getch();
exit(1);
}
cout<<"Informatia atasata nodului:";
cin>>p_1->k;
p_1->next=NULL;
if(prim==NULL)
prim=ultim=p_1;
else
{ ultim->next=p_1;
ultim=p_1;
}
}while (1);
}
Lista::~Lista(){
nod*p=prim,*p_1;
clrscr();
cout<<"Distrugerea listei";
while(p!=NULL){
p_1=p;
p=p->next;
delete p_1;
}
}
void Lista::insert(nod*p,int cheie)
{
nod*p_1;
p_1=prim;
int gasit=0;
while(p_1!=NULL&&!gasit)
{
if(p_1->k==cheie)gasit=1;
else p_1=p_1->next;
}
if(!gasit){
cout<<"\n Nu s-a identificat un element din lista cu cheia:"<< cheie; getch(); return; } else{ p->next=p_1->next;
p_1->next=p;
if(p_1==ultim) p=ultim;
}
}
void Lista::elimin(int cheie)
{
nod*p_1,*p_2;
p_1=prim;
if(prim==NULL){
cout<<"Lista vida";
return;
}
if(p_1->next==NULL){
if(p_1->k==cheie){
prim=ultim=NULL;
return;
}
else {
cout<<"Nu se afla un element cu cheia";
cout<< cheie;
return;
}
}
else{
if(p_1->k==cheie){
prim=prim->next;
delete p_1;
return;
}
else{
while(p_1->next!=NULL)
{
p_2=p_1->next;
if(p_2->k==cheie){
p_1->next=p_2->next;
delete p_2;
cout<<"\n Am eliminat
un nod din lista";
return;
}
p_1=p_2;
}
cout<<"\n Nu se afla nod
cu codul dat";
}
}
}
void Lista::afis()
{
nod*p=prim;
int lin=0,col=60;
while(p!=NULL)
{
if(lin>=21)
{
gotoxy(10,22);
cout<<"\n Actionati o tasta pentru a continua";
getch();
lin=1;
col=1;
}
if(col>50)
{
lin+=1;
col=1;
}
else col+=25;
gotoxy(col,lin);
cout<<p->k;
p=p->next;
}
}
void ecran()
{
clrscr();
gotoxy(10,10);
cout<<"Afisare:";
gotoxy(10,11);
cout<<"Inserare:";
gotoxy(10,12);
cout<<"Stergere:";
gotoxy(10,13);
cout<<"Exit:";
}
void main(void)
{
nod*p;
char c;
int cheie;
Lista L;
do
{
ecran();
c=getch();
clrscr();
switch(c)
{
case'A': L.afis();
break;
case'I': cout<<"Inserez un element in lista \n";
p=new nod;
if(!(p))
{
cout<<"Memorie insuficienta";
getch();
exit(1);
}
cout<<"Se da informatia atasata nodului";
cin>>p->k;
cout<<"\n Se da codul nodului dupa care
se va insera nodul citit";
cin>>cheie;
L.insert(p,cheie);
break;
case'S': cout<<"\n Se da codul nodului care se va
sterge:"; cin>>cheie; L.elimin(cheie); break;
case'E': exit(1);
}
getch();
}while(1);
}
• Obiectele trebuie sa fie initializate. Initializarea lor se poate realiza:
a) cu ajutorul listelor de initializare
Exemplu:
struct fisier
{
FILE *fp;
char *nume;
int lung_art;
};
fisier fd={stdin,"file.bin",80}; //initializare corecta
fisier hd={stdout};
//initializare corecta,restul membrilor luand in mod implicit valoarea 0
In lista de initializare nu se accepta mai multe valori decat numarul campurilor prezente in struct.
Exemplu:
class fisier
{
public:
FILE *fp;
char *nume;
int lung_art;
};
fisier fd={stdin,"file.bin",80}; //initializare corecta
Sa observam ca, in class, initializarea variabilei fd se poate realiza, numai daca membrii clasei sunt declarati in sectiunea public. In plus, pentru astfel de obiecte, nu vor exista constructori, functii virtuale, nu pot proveni din clase derivate [aceste concepte vor fi precizate pe parcurs].
b) cu ajutorul constructorilor.
Obiectele se pot initializa in momentul instantierii (creerii) lor. In acest sens se utilizeaza unele functii membre speciale ale clasei numite constructori.
• Constructorii sunt utili in:
-initializarea obiectelor;
-alocarea dinamica de memorie;
-deschideri de fisiere etc.
• Constructorul este o functie membra a unei clase care se apeleaza automat la crearea fiecarui obiect, inclusiv pentru obiecte temporare, si se identifica cu acelasi nume ca si clasa din care face parte.
• Functia constructor nu contine tip de valoare returnata (nu retuneaza nici o valoare) si nu poate fi functie virtuala [vezi L9].
• Ca orice functie membra, un constructor admite mai multe prototipuri. Listele de parametri ale diferitelor variante de implementare trebuie sa fie diferite pentru a putea sa fie identificate corect de catre compilator.
• Parametrii unui constructor pot fi de orice tip, cu exceptia tipului definit de clasa ce contine acest constructor. Unii dintre acesti parametri pot fi pointeri sau referinte la o instanta a clasei respective.
Exemplu:
class A
{
……………..
A(A a); // incorect
…………………..
A(A*a); // corect, parametrul este un pointer la tipul definit prin clasa A
…………………….
A(A& a); // corect, parametrul este o referinta la un obiect al clasei A
}
• Un constructor poate fi:
a) implicit
- fara parametri (definit de utilizator) care poate contine in corpul sau orice fel de instructiuni valide. Un constructor „inline“ nu poate contine instructiuni cu caracter repetitiv.
- generat de compilator (cand nu exista constructori definiti de utilizator in clasa respectiva). Corpul unui astfel de constructor nu contine nici o instructiune.
b) cu parametri care iau valori in mod implicit
c) cu parametri care nu iau valori implicite
d) cu conversie de tip
e) de copiere
- definit de utilizator
- generat implicit de compilator
• La initializare, daca in clasa respectiva exista mai multi constructori, se va tine cont, la apelul lor, de lista de parametri (numarul si tipul lor) solicitata de instantierea respectiva. Daca exista un singur constructor, atunci se aplica aceleasi reguli ca la apelul functiilor din limbajul C. Ca atare, tipurile parametrilor efectivi (expresiile care vor produce initializarea) se vor converti la tipurile parametrilor formali corespunzatori ai constructorului.
• Transmiterea parametrilor actuali catre functia constructor, utili pentru initializarea unui obiect, se realizeaza in momentul creerii acestuia.
ident_clasa ident_obiect (lista);
Lista contine una sau mai multe expresii separate prin virgula. Daca nu se produce o initializare a obiectului, lista si parantezele lipsesc.
Exemplu:
class data_c{
int zi,luna,an;
public:
// initializare, constructor fara parametri (implicit)
data_c( )
{
zi=15;
luna=1;
an=1999;
}
//initializare, constructor cu parametri tip int, ultimul cu valoare implicita
data_c(int z, int l, int a=1999)
{
zi=z;
luna=l;
an=a;
}
//initializare, constructor care contine ca param. denumirea lunii
data_c(int z, char*den_l, int a);
………………..
};
Exemple de instantieri ale clasei data_c.
1) data_c d1; se apeleaza constructorul fara parametri si se obtine pentru obiectul d1: zi=15,luna=1,an=1999.
2) data_c d2(12,4,1999); se apeleaza constructorul cu toti parametri de tip int si se obtine pentru obiectul d2: zi=12, luna=4, an=1999.
3) data_c d3(12,4); se apeleaza acelasi constructor ca la d2 obtinand acelasi rezultat.
4) data_c d4(18, "ianuarie", 1999); se apeleaza ultimul constructor si se obtine pentru obiectul d4: zi=18, luna=ianuarie, an=1999.
5) data_c *pd=new data_c(18,1); se apeleaza constructorul la fel ca pentru obiectele d2 si d3 in vederea initializarii, in plus, se va realiza si o alocare de memorie heap pentru obiectul creat, iar pd are ca valoare adresa de inceput a zonei alocate obiectului respectiv.
• Datele membre ale unui obiect (de durata locala sau dinamica) daca nu au fost initializate, vor primi valori necontrolabile (imprevizibile).
• Daca intr-o clasa este prezent un constructor implicit, atunci nu se mai poate defini pentru clasa respectiva un constructor cu toti parametrii impliciti, pentru ca s-ar produce ambiguitati la instantierea obiectelor.
• Prezenta constructorilor intr-o clasa nu este obligatorie, deoarece compilatorul C++ genereaza in mod automat un constructor fara parametri (constructor implicit), care are rolul doar de alocare pentru instanta respectiva.
• Spre deosebire de alte functii membre ale unei clase, adresa unui constructor nu se poate determina.
• Constructorii definiti de programator sunt necesari atunci cand se doreste initializarea obiectelor odata cu crearea lor. Daca o clasa are cel putin un constructor si nici unul dintre ei nu este implicit, atunci nu se pot instantia obiecte neinitializate, deoarece compilatorul nu genereaza constructor implicit intr-o astfel de situatie.
Exemplu:
class complex {
double real;
double imag;
public:
complex(double x, double y)
//initializarea se realizeaza prin asignari
{
real=x;
imag=y;
}
………………
};
Se pot instantia numai obiecte de tip complex cu ambii membri initializati.
Exemplu:
complex z(4,-2);
complex u; // este incorect pentru ca nu exista constructor implicit.
• Intr-un constructor pot fi apelate si alte functii care pot fi, sau nu, functii membre ale clasei respective.
Exemplu:
class Pers{
private:
char nume[25];
long salariu;
public:
Pers(char *,long); // constructor cu parametri neimpliciti
long Sal( ) {return salariu;} //functie membra
};
Pers::Pers(char*n,long l){
strcpy(nume,n); // functie ne-membra a clasei Pers
salariu=l;
}
• Constructorul garanteaza initializarea corecta a obiectului inainte de utilizarea efectiva a sa. El ofera o garantie, in plus, asupra faptului, ca initializarea unui obiect se va efectua o singura data.
• Apelul constructorului se realizeaza in momentul declararii unui obiect.
Exemplu:
Pers p=Pers("Goga",1987345);
sau
Pers p("Goga",1987345);
• Daca un constructor are un singur parametru, initializarea se realizeaza in mod obisnuit.
Exemplu:
# include <iostream.h>
class U
{
int k;
public:
U(int c){k=c;} //constructor cu un singur parametru
int afis() {return k;}
};
main( )
{
U ob=23; // se transmite valoarea 23 lui c
cout <<ob.afis( ); // se afiseaza 23
return 0;
}
• Un constructor poate avea toti parametrii cu valori implicite.
Exemplu:
class Pers{
private:
char nume[23];
long salariu;
public:
//constructor care are parametrii cu valori implicite
Pers(char*p="Nume", long s=1987345);
………………………………………….
};
Pers::Pers(char*n,long s)
{
strcpy(nume,n);
salariu=s;
}
• Valorile parametrilor impliciti sunt prezente in declaratia constructorului si nu in cadrul implementarii sale. Apelul unui astfel de constructor se poate realiza sub una din urmatoarele forme:
Pers p1;
Pers p2("Goga");
Pers p3("Goga",1987345);
Pers p4=Pers( );
• Varianta constructorului cu parametrii ce iau valori implicite se poate folosi atunci cand constructorul nu necesita argumente (parametri efectivi) si el se va identifica cu un constructor implicit. Apelul sau se va face sub forma unei simple declaratii.
• In mod normal, constructorii se afla in zona „public“, mai rar in sectiunea "private". Daca un constructor este declarat in sectiunea „private“, el poate fi apelat doar de o alta functie membra sau functie friend. Prin urmare, numai functiile membre si friend pot crea obiecte avand constructori privati. O astfel de clasa se mai numeste si clasa privata.
• Declaratia obiectelor a caror lista de initializare se reduce la un parametru se poate scrie intr-un format asemanator cu cel de la initializarea variabilelor simple.
ident_clasa ident_obiect = expresie;
In aceasta situatie se apeleaza un constructor in care primul parametru ia ca valoare, valoarea "expresie" iar ceilalti parametri, daca exista, au valori implicite.
Exemplu:
# include <iostream.h>
class complex
{
double real;
double imag;
public:
complex(double x, double y=10)
{
real=x;
imag=y;
}
void afis( );
};
void complex::afis( )
{ if (imag<0)
cout<<real<<imag<<"*i\n";
else
cout<<real<<"+"<<imag<<"*i\n";
}
void main ( )
{ double r=3.2;
complex z1(2.56);
z1.afis();
complex z2=3*r-1;// se atribuie o expresie obiectului z2
z2.afis( );
complex z3(18.5,-9);
z3.afis( );
}
• Daca se doreste a se instantia obiecte atat initializate cat si neinitializate atunci se va folosi un constructor implicit (fara parametri), care va fi apelat la instantierea obiectelor neinitializate.
• Pentru a nu se ajunge la obiecte, care nu se pot identifica si deci initializa, nu trebuie apelat un constructor in interiorul unui alt constructor.
• In cazul in care o clasa are obiecte membre, care au constructori, acestia se apeleaza inainte de a se apela constructorul clasei respective.
• Constructorii cu conversie de tip au primul parametru de tip diferit de cel al clasei apelante. Daca mai exista si alti parametri, ei trebuie sa aiba valori implicite.
Exemplu:
class pers
{
........................
public:
pers(char*nume, long s=1987345)
............................
}
main( )
{
....................
pers t=”Horia”; // se converteste char* la pers
...................
}
• Constructorul de copiere este un constructor special care permite copierea de obiecte. Prin prezenta lui se renunta la copierea pe biti. El are ca prim parametru o referinta catre clasa din care face parte ca functie membra, iar daca mai exista si alti parametri, acestia iau valori in mod implicit.
Sintaxa:
id_clasa (const id_clasa &…);
El este util doar pentru initializari.
• Un constructor poate fi apelat explicit in situatii de genul urmator:
id_clasa ob= id_clasa (lista par_actuali);
In acest caz este apelat constructorul clasei “id_clasa” pentru a creea un obiect anonoim care va fi copiat in ob.
Exemplu:
# include <iostream.h>
class complex
{
double real;
double imag;
public:
complex(double x=10, double y=10)
{
real=x;
imag=y;
}
complex(const complex &u) // constructor de copiere
{
real=u.real;
imag=u.imag;
}
void afis( );
};
void complex::afis( )
{ if (imag<0)
cout<<real<<imag<<"*i\n";
else
cout<<real<<"+"<<imag<<"*i\n";
}
void main ( )
{
complex z1(2.56,101.99);
z1.afis();
complex z2=z1;// se aplica constructorul de copiere
z2.afis( );
complex z3(z1); // idem
z3.afis( );
//crearea unui obiect anonim care este copiat in z
complex z=complex(1.2,3.5);
z.afis( );
}
Exemplu:
class tablou_2D{
int*p;
int dim;
public:
tablou_2D(int d){
p=new int [d];
if(!p)exit(1);
dim=d;
}
~tablou_2D(){delete[]p;}
//constructor de copiere
tablou_2D(const tablou_2D &t);
void asign(int i,int j)
{
if(i>=0&&i<dim)p[i]=j;
}
int ret(int i){return p[i];
}
};
tablou_2D::tablou_2D(const tablou_2D &t)
{
int i;
p=new int [t.dim];
if(!p)exit(1);
for(i=0;i<t.dim;i++)
p[i]=t.p[i];
}
main()
{
tablou_2D X(;
int i;
for(i=0;i<8;i++)
X.asign(i,i);
for(i=7;i>=0;i--)
cout<<X.ret(i);
cout<<"\n";
tablou_2D y=X;
//se apeleaza constructorul de copiere
for(i=0;i<8;i++)
cout<<X.ret(i);
return 0;
}
• Daca se solicita un constructor de copiere si nu a fost definit de utilizator, atunci compilatorul va genera unul implicit. Elementele membre sunt copiate de la obiectul sursa la obiectul destinatie, in ordinea declararii lor in clasa.
• Initializarea elementelor membre ale unui obiect se poate face printr-un constructor care foloseste o lista de initializare.
Exemplu:
class complex{
double re,im;
public:
complex(double x, double y); // constructor - prototip
};
//lista de initializare a membrilor
complex::complex(double x, double y):re(x),im(y)
{return;}
Ordinea instantierilor este data de cea indusa prin declararea membrilor in clasa si nu de ordinea din lista de instantiere.
Exemplu:
class punct{
public:
int re,im;
punct(int x, int y){re=x; im=y;}
};
class vector {
punct varf, orig;
vector (int xv, int yv, int xo, int yo);
};
vector::vector(int xv, int yv, int xo, int yo):varf(xv,yv), orig(xo,yo)
{return;}
Ce puteti afirma despre "constructiile" de forma data mai jos si eventual, realizati secvente de program C++ in care sa le utilizati.
romb::romb(ind dl, float da)
tnod::tnod( )
arena::arena(double *x=5.0)
clasa::clasa(int u)
alfa::alfa(alfa&s)
• Daca un membru al unei clase este un pointer la o clasa, atunci nu se poate apela constructorul acelei clase in cadrul listei de instantiere.Constructorii nu pot fi apelati pentru pointeri la obiecte, ci numai pentru obiecte.
• Se accepta ca un membru al unei clase sa fie o referinta la un obiect. In acest caz referinta trebuie sa fie initializata in momentul in care este creat obiectul care contine referinta.
Exemplu:
class B
{
public:
int obs;
int &noutate;
B(int k); // constructor
};
B::B(int k):obs(k),noutate(obs); // lista de initializare
{return;}
• Membrii de tip referinta sau constanti trebuie initializati intr-o lista de instantiere. Ca atare clasele care vor avea astfel de membri, obligatoriu vor contine un constructor.
• Am vazut ca un constructor este necesar atat la initializarea unui obiect al unei clase cat si la alocarea dinamica de memorie pentru el. O alta functie membra speciala, care are rolul de a dezactiva toate functiile unui obiect creat in mod dinamic, este destructorul. Se poate spune ca destructorul distruge un obiect creat. Ca atare, destructorul este folosit in cadrul obiectului al carui constructor realizeaza o alocare dinamica de memorie. Ca si constructorii, destructorii pot efectua diverse alte operatii.
• Un destructor se identifica prin acelasi identificator ca si clasa al carei membu este, precedat de simbolul "~". Este vorba de „negarea“ unui constructor.
~iden_clasa( );
• Un destructor nu are parametri si nu contine tip de valoare returnata.
• Reamintim ca un constructor de obiecte este executat cand se intalneste instructiunea de declarare a obiectului. Daca se declara doua sau mai multe obiecte in aceeasi instructiune, constructorii sunt apelati in ordinea declararii de la stanga la dreapta.
• Functiile destructor, pentru obiecte locale, se executa in ordine inversa fata de constructorii care s-au folosit la instantiere.
• Functiile constructor pentru obiectele globale se executa inaintea functiei main(). Destructorii globali se executa in ordine inversa si dupa ce s-a incheiat functia main( ).
• Apelul destructorului se produce,in mod automat, in timpul executiei programului, cand se incheie domeniul de valabilitate (existenta) al obiectului respectiv. Nu este necesar un apel explicit al unui destructor.
• Destructorii obiectelor membre sunt apelati dupa ce destructorul obiectului principal a fost executat. Daca obiectul membru este compus din alte obiecte, atunci se va proceda la executia destructorilor obiectelor incluse.
• Daca obiectul este local unei functii, apelul destructorului se face inainte de a se iesi din functia respectiva, iar daca obiectul este static, apelul destructorului corespunzator se va face inainte de a se termina executia programului principal.
• O clasa nu poate avea mai mult de un destructor, pentru ca el nu poate fi redefinit. #n general, un destructor se declara in sectiunea public.
• La o declarare privata a unui destructor, accesul la el se poate face doar cu functii membre ale obiectului respectiv sau functii prieten (friend).
• Antetul destructorului in exteriorul clasei:
iden_clasa ::~iden_clasa( )
• Adresa unui destructor nu poate fi determinata.
Exemplu:
# include <iostream.h>
class EXE{
public:
int beta;
EXE(int par); //constructor
~EXE( ); //destructor
}ob_1(1),ob_2(2);
EXE::EXE(int par){
cout<<"AFISEAZA_INITIALIZAREA"<<par<<"\n";
beta=par;
}
EXE::~EXE( ){
cout<<"DISTRUGEREA"<<beta<<"\n";
}
main( ){
EXE ob1_local(3);
cout<<"SCRIE:\n";
EXE ob2_local(4);
return 0;}
Ce se va afisa?
Aplicatie:
Sa se realizeze un program prin care sa se afiseze un anumit numar de salariati ai unei intreprinderi impreuna cu salariile lor. Se vor utiliza constructori si destructori pentru creare, respectiv distrugere de obiecte,operatorii new si delete pentru alocare, respectiv eliberare a unei zone de memorie alocata dinamic.
#include <iostream.h>
#include<conio.h>
#include<string.h>
class persoana{
private:
char *nume;
long sal;
void init(char *s=NULL,long u=0){
nume=new char[strlen(s)+1];
strcpy(nume,s);
sal=u;
}
public:
persoana( )
{init( );}
persoana(char*s,long u)
{init(s,u);}
~persoana( )
{delete nume;}
void afis( )
{cout<<nume<<"...are salariul:"<<sal<<"tn";}
void introd(char*s,long u)
{init(s,u);}
};
class serviciu{
private:
persoana*pers;
int npers;
public:
serviciu(int n=0){
npers=n;
pers=new persoana[npers];
}
~serviciu( ){delete pers;}
void intr(int n);
void afis_1( );
};
void serviciu::intr(int n){
char s[30];
long u;
int i;
npers=n;
for(i=0;i<npers;i++){
cin>>s>>u;
pers[i].introd(s,u);
}}
void serviciu::afis_1( ){
int i;
for(i=0;i<npers;i++){
pers[i].afis( );
}
}
void main( ){
serviciu serv;
clrscr( );
serv.intr(5);
serv.afis_1( );
getch( );
}
Aplicatie:
Sa se implementeze o clasa „Stiva“ in care elementele sa fie de tip intreg. Sa se implementeze functiile membre care sa adauge cate un element in stiva, respectiv, sa extraga cate un element din stiva. O alta functie membra sa poata afisa stiva in orice moment care se doreste.
#include <iostream.h> #include <conio.h> #include <stdlib.h> class nod{ public: int cheie; nod* next;}; class Stiva{ nod*cap; public:
Stiva( ) {cap=NULL;}
~Stiva( );
int pop( );
void push(int);
void afis( );
};
void Stiva::push(int x){
nod *p;
if ((p=new nod)==NULL)
{cout<<"Memorie insuficienta!";
getch( );
exit(1);
}
p->next=cap;
p->cheie=x;
cap=p;
}
int Stiva::pop( ){
if(!cap)
{cout<<"Stiva vida";
getch( );
exit(1);
}
nod*p=cap;
int t;
t=cap->cheie;
cap=cap->next;
delete p;
return t;
}
void Stiva:: afis( ){
nod*p=cap;
while (p!=NULL)
{cout<<p->cheie;
p=p->next;
}
}
Stiva::~Stiva( ){
nod*p;
while(cap!=NULL){
p=cap;
cap=cap->next;
delete p;
}
}
void ecran( ){
clrscr( );
gotoxy(9,9);
cout<<"1:Pune";
gotoxy(9,10);
cout<<"2:Sterge";
gotoxy(9,11);
cout<<"3:Afisare";
gotoxy(9,12);
cout<<"4:Exit";
gotoxy(9,13);
}
void main ( ){
Stiva V;
int cheie;
char c;
do{
ecran( );
c=getch( );
clrscr( );
switch(c){
case'+':cout<<"Se da cheia datei care se introduce:";
cin>>cheie;
V.push(cheie);
break;
case'-':cout<<"Am extras din stiva:"<<V.pop( );
getch( ); break;
case'a':V.afis( );
getch( );
cout<<"";
break;
case'e':exit(1);
}
}while(1) ;
}
Aplicatie
Sa se defineasca un tip abstract „Lista“. Sa se implementeze o lista simplu inlantuita si cu ajutorul a doi pointeri sa se realizeze operatiile de inserare, respectiv, stergere de noduri din lista.
#include <iostream.h> #include <stdlib.h> #include <conio.h> class nod{ public: int k; nod*next;
};
class Lista{
nod*prim,*ultim;
public:
Lista();
~Lista();
void insert(nod*,int);
void elimin(int);
void afis();
};
Lista::Lista(){
char c;
nod*p_1;
prim=ultim=NULL;
do{
cout<<"tn Continuati:Y/N";
cin>>c;
if(c!='Y'&&c!='y') break;
p_1=new nod;
if(!(p_1)){
cout<<"Memorie insuficienta!";
getch();
exit(1);
}
cout<<"Informatia atasata nodului:";
cin>>p_1->k;
p_1->next=NULL;
if(prim==NULL)
prim=ultim=p_1;
else
{ ultim->next=p_1;
ultim=p_1;
}
}while (1);
}
Lista::~Lista(){
nod*p=prim,*p_1;
clrscr();
cout<<"Distrugerea listei";
while(p!=NULL){
p_1=p;
p=p->next;
delete p_1;
}
}
void Lista::insert(nod*p,int cheie)
{
nod*p_1;
p_1=prim;
int gasit=0;
while(p_1!=NULL&&!gasit)
{
if(p_1->k==cheie)gasit=1;
else p_1=p_1->next;
}
if(!gasit){
cout<<"\n Nu s-a identificat un element din lista cu cheia:"<< cheie; getch(); return; } else{ p->next=p_1->next;
p_1->next=p;
if(p_1==ultim) p=ultim;
}
}
void Lista::elimin(int cheie)
{
nod*p_1,*p_2;
p_1=prim;
if(prim==NULL){
cout<<"Lista vida";
return;
}
if(p_1->next==NULL){
if(p_1->k==cheie){
prim=ultim=NULL;
return;
}
else {
cout<<"Nu se afla un element cu cheia";
cout<< cheie;
return;
}
}
else{
if(p_1->k==cheie){
prim=prim->next;
delete p_1;
return;
}
else{
while(p_1->next!=NULL)
{
p_2=p_1->next;
if(p_2->k==cheie){
p_1->next=p_2->next;
delete p_2;
cout<<"\n Am eliminat
un nod din lista";
return;
}
p_1=p_2;
}
cout<<"\n Nu se afla nod
cu codul dat";
}
}
}
void Lista::afis()
{
nod*p=prim;
int lin=0,col=60;
while(p!=NULL)
{
if(lin>=21)
{
gotoxy(10,22);
cout<<"\n Actionati o tasta pentru a continua";
getch();
lin=1;
col=1;
}
if(col>50)
{
lin+=1;
col=1;
}
else col+=25;
gotoxy(col,lin);
cout<<p->k;
p=p->next;
}
}
void ecran()
{
clrscr();
gotoxy(10,10);
cout<<"Afisare:";
gotoxy(10,11);
cout<<"Inserare:";
gotoxy(10,12);
cout<<"Stergere:";
gotoxy(10,13);
cout<<"Exit:";
}
void main(void)
{
nod*p;
char c;
int cheie;
Lista L;
do
{
ecran();
c=getch();
clrscr();
switch(c)
{
case'A': L.afis();
break;
case'I': cout<<"Inserez un element in lista \n";
p=new nod;
if(!(p))
{
cout<<"Memorie insuficienta";
getch();
exit(1);
}
cout<<"Se da informatia atasata nodului";
cin>>p->k;
cout<<"\n Se da codul nodului dupa care
se va insera nodul citit";
cin>>cheie;
L.insert(p,cheie);
break;
case'S': cout<<"\n Se da codul nodului care se va
sterge:"; cin>>cheie; L.elimin(cheie); break;
case'E': exit(1);
}
getch();
}while(1);
}
Subiecte similare
» Manevrarea dinamica a obiectelor unei clase
» Mostenire clase de baza clase derivate
» Crearea tabelelor
» Serializarea obiectelor in Java
» Crearea si editarea paginii html
» Mostenire clase de baza clase derivate
» Crearea tabelelor
» Serializarea obiectelor in Java
» Crearea si editarea paginii html
Informatica :: IT :: C++
Pagina 1 din 1
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum