Pagina de start a forumului Informatica
 FAQ  •  Cautare  •  Membri  •  Grupuri   •  Inregistrare  •  Profil  •  Mesaje private  •  Autentificare
Subiectul urmator
Subiectul anterior
Creaza un subiect nou   Raspunde la subiect  Pagina de start a forumului Informatica » C++
Autor Mesaj
Admin
Administrator
Administrator


Data inscrierii: 07/Dec/2013
Mesaje: 1103

MesajTrimis: 14/12/2013 19:26 Raspunde cu citat (quote) Back to top

• Atat functiile cat si datele membre ale unei clase se pot declara static. In mod firesc, un obiect poseda o copie proprie a variabilelor instantiate ale clasei din care provine. Exista probabilitatea de a defini membrii care sunt comuni tuturor obiectelor clasei respective. Ei sunt membri statici si se vor declara cu ajutorul cuvantului cheie static. Asadar, spre deosebire de membrii obisnuiti ai unei clase, pentru membrii de tip static, nu se mai creaza copii individuale pentru fiecare obiect, indiferent de numarul de obiecte ale clasei respective.
Cand se creaza primul obiect, toate variabilele de tip static sunt initializate cu zero.

• Trebuie inteles, ca in C++, o declaratie este echivalenta cu o descriere a datei respective, iar o definire inseamna de fapt, existenta acelei date. De aceea, cand se declara o data membra statica intr-o clasa, nu o definim si deci nu i se aloca memorie. Pentru acesti membri statici trebuie sa se dea o definitie globala in exteriorul clasei. Este necesar a se face o distinctie intre utilizarea cuvantului cheie static prin care se declara variabile statice si membrii statici ai unei clase.
Exemplu:
class secventa{
public:
char*caractere;
int dim,lung;
static char ss; //membru static
secventa(int d); //constructor cu un parametru
…………………….
};
void main( ) {
secventa o1,o2,o3; // instantiere fara initializare
…………………….
};

Fiecare din cele trei obiecte o1,o2,o3 apartin aceleiasi clase secventa. Ele vor avea un "continut" propriu (dim,lung), dar cu un acelasi sfarsit de sir de caractere "ss" prezent ca membru static.
Faptul ca se va actiona asupra tuturor celor trei obiecte de acest tip va fi pus in evidenta printr-o declaratie de forma:
tip id_clasa::id_membru_static=…

Exemplu: char secventa::ss='$';
ceea ce este mai convenabil decat succesiunea
secventa o1(60);
o1.ss='$';…….

Exemplu:
# conține <iostream>
class exemplu{
static int x;//membru static al clasei exemplu
int y;
public:
void init(int , int );
void afis( );
};
int exemplu::x; //defineste x in exteriorul clasei
void exemplu::afis( ){
cout<<"Scrie pe x (static):"<<x;
cout<<"Scrie pe y (nestatic):"<<y;
cout<<"\n";
};
void exemplu::init(int a,int b){x=a;y=b;}
void main( ){
exemplu u,v;
u.init(1,1); //se initializeaza x cu 1
u.afis( );
v.init(3,3); //valoarea lui x se schimba, devine 3
v.afis( );
u.afis( );
//valoarea lui x se schimba, pentru ca x este comun pentru ambele
// obiecte
}

Se observa ca x a fost declarat ca penis static in clasa exemplu, dar, obligatoriu, este definit in exteriorul acestei clase pentru a i se putea aloca memorie.

• Instantierea unui membru static se poate face fie in programul principal, fie inaintea sa, dar nu in declararea unei clase. De regula,instantierea membrilor statici se va realiza in acelasi fisier in care se implementeaza metodele (functiile membre) ale clasei respective.

• Cand se initializeaza un membru static nu se mentioneaza cuvantul cheie static.
Exemplu:
#include<iostream> class model
{ public: static int k; }; int model::k; //definirea variabilei statice k main()
{ model::k=1999;//initializarea
cout<<"Valoarea initiala a lui k:"<<model::k;
cout<<"\n";
model b; // creare obiect al clasei model
cout<<"Valoarea lui b.k:"<<b.k;
return 0; }
Se observa ca variabila membra k este declarata static. Ea exista inainte de a fi creat indiferent ce obiect al clasei respective, si se poate initializa oriunde. Variabila k fiind o variabila statica si publica, se poate utiliza direct in functia principala main( ). }i dupa creerea obiectului b, valoarea lui k ramane nemodificata.

• De regula, variabilele membre statice, se folosesc cu scopul de a asigura controlul accesului la unele resurse comune. Mai exact, se pot crea mai numeroase obiecte, fiecare avand posibilitatea sa scrie intr-un fisier pe disc. Deoarece, doar un solitar obiect are dreptul sa scrie intr-un fisier la un clipă dat, vom declara o variabila statica care va indica timpul in care este folosit fisierul si cand acesta este liber. Fiecare obiect va controla aceasta variabila statica inainte de a scrie in fisier.

Exemplu:
#include <iostream>
class control
{ static int gest; public: int ocup(); void liber(){gest=0;} };
int control::gest; //se defineste variabila statica gest
int control::ocup()
{
if(gest)return 0; //opereaza gest
else{
gest=1;
return gest;}
// gest este assignata obiectului
}
main()
{
control ob_1,ob_2;
if(ob_1.ocup())
cout<<"ob_1 are acces la gesttn";
if(!ob_2.ocup())
cout<<"ob_2 nu are acces la gesttn";
ob_1.liber(); //gest este liber
if(ob_2.ocup())
cout<<"ob_2 poate folosi gesttn";
return 0;
}

• Datele membre statice se initializeaza in afara constructorilor tocmai pentru ca o astfel de data reprezinta o zona comuna care nu se multiplica la fiecare instantiere a clasei respective. De aceea, o astfel de initializare se cauzează odata cu definirea datei respective, in exteriorul oricarei functii.
Exemplu:
class student
{
char nume[25];
int varsta;
static int an_stud;
static long int bursa;
};

Initializarea datelor membre statice:
int student::an_stud=2;
long int student::bursa= 800000;
Daca ar lipsi identificatorul clasei si operatorul "::", datele respective ar deveni date globale care se initializeaza cu valorile respective.

Asignari de forma:
student::an_stud=2;
student::bursa= 800000;
sunt admise daca ele se afla in trupul unei functii membre (date protejate) a clasei respective.
Astfel de atribuiri, de regula, nu se considera initializari si se folosesc, cand se apeleaza functia membra care le contine. O astfel de „initializare“ nu se accepta pentru date membre statice. Daca astfel de date nu sunt perfect initializate, ele vor primi automat valoarea zero, daca este setata optiunea “initializare implicita cu zero”.
Exemplu:
#include<iostream> #include<math> class complex
{ float re,im; static int nr_ob; //variabila membra statica public: char c; void afis( );
static void init(int,int); //functie membra statica (prototip)
}ob;
void complex::afis( ){cout<<ob.re<<"+i*("<<ob.im<<")";}
void complex::init(int a,int b){ob.re=a;ob.im=b;}
void main( )
{
char c;
int nr_ob=0,b_2=8,b_1=32;
complex o1;
o1.init(b_1++,b_2--);
nr_ob++;
o1.afis ( );
cout<<"tn";
do{
complex o1;
o1.init(b_1++,-b_2--);
nr_ob++;
o1.afis( );
cout<<"\n";
}while (b_2!=0);
cout<< \n";
cout<<"Nr_obiecte create:"<<nr_ob;
}

• Nu se accepta initializarea unor variabile membre statice, daca domeniul de existenta al clasei respective este local.

• Membrii statici privati se pot initializa in acelasi fel, dar accesul la ei va respecta regimul privat.

• Variabilele globale, ca si membrii statici, au acelasi rol, dar numele lor nu va fi protejat in interiorul unei clase. Daca se folosesc membrii statici, se obtine o combinatie intre date globale si locale prezente in acea clasa. întrebuințarea variabilelor membre statice conduce la eliminarea a cat mai multe variabile globale din program.
Analizati urmatoarea secventa si semnalati erorile care apar:
class punct
{
public:
static int x0,y0;
int x,y;
punct(int xi, int yi);
};
punct::x0=28;
static int y0=30;
int punct::x0=28;
int punct::y0=30;

• Un pointer la un membru static al unei clase este interpretat ca un pointer obisnuit, in schimb, el se deosebeste de cel obisnuit prin sintaxa definirii lui.
Exemplu:
class A
{
public:
//.......................
static float f;
private:
//.......................
};
// Se defineste un pointer la variabila membra statica a clasei A
float *p.f=&A::f;

• Exista o înșiruire de restrictii atunci cand se declara static unele functii membre ale unei clase:
a) Ele au acces doar la membrii de tip static ai clasei si bineinteles, la functiile si datele globale.
b) Nu pot avea un pointer de tip this.
c) Nu poate exista, pentru aceeasi functie, o versiune statica si una nestatica.
d) Functiile membre statice au aplicatii limitate, iar o corecta folosire a lor impune o preinitializare a datelor private de tip static, inainte de crearea efectiva a unui obiect.
Exemplu:
# include <iostream>
class ex_static
{
static int k;
public:
static void init(int u){k=u;}
void afis( ){cout<<k;}
};

int ex_static::k; // defineste obiectul k
void main ( )
{
ex_static::init(500);
// se initializeaza data statica inainte de crearea obiectelor
ex_static u;
u.afis( );
}

• O variabila constanta se declara astfel:

const tip iden_var=valoare;
Exemplu: const int x=12;

• Un obiect constant se declara astfel:

const tip_clasa iden_ob(l1,l2,…);
Exemplu: const punct O(0,0);

• Daca se declara un obiect constant, atunci este permisa numai apelarea functiilor membre ale acestuia care au fost declarate constante. #ntr-o clasa, functiile membre constante se declara utilizand cuvantul cheie const plasat imediat dupa inchiderea parantezelor ce cuprind parametrii functiei respective. Printre functiile membre ale unui obiect constant care pot fi apelate se afla si constructorii care nu vor fi declarati constanti.

Exemplu:
class complex{
private:
double re,im;
public:
complex(double x0, double y0){re=x0; im=y0;}
int valoarea( )const {return…;}
void afis( );
………………………..
};

void main( )
{
const complex z(2,3);
double w=z.valoare( );
…………………….
}

• Accesul la datele membre ale unei clase se poate realiza prin apelarea unei functii de acces, aspect caracteristic incapsularii, dar el necesita un consum semnificativ de timp. Se stie ca la apelul unei functii, parametrii sunt depusi in memoria stiva, sunt salvati in mai multe registre si apoi rememorati cand se realizează returnarea. Exista insa functiile inline, des utilizate in C++, care sunt folosite in mod uzual impreuna cu clasele. O astfel de functie este o functie de mărime mica care nu se apeleaza, codul ei dezvoltandu-se in interior, in fiecare punct in care se identifica. Definitia ei este precedata de cuvantul cheie inline.
Exemplu:
# include <iostream>
inline int min(int u, int v)
{
return u<v?u:v;
}
main( )
{ cout<<min(100,50);
…………………
return 0;
}

• O declarare „inline“ implicita consta in definirea unei astfel de functii in corpul unei clase. Se poate vorbi si de o declarare explicita a unei astfel de functii, daca ea este doar declarata in trunchiul clasei in care este functie membra, iar definirea propriu-zisa a sa se va face in exteriorul clasei utilizând cuvantul cheie inline. O functie definita in declararea unei clase, automat este transformata intr-o functie inline, chiar daca nu este precizat cuvantul cheie inline in definitia sa.
Exemplu:
class student
{
private:
char nume[25];
char adresa[30];
public:
char*Adresa( ) {return adresa;} // automat este o functie inline
char*Nume( ){return nume;} // idem
…………………………………
};

• Exista restrictii referitor la functiile inline pentru ca ele sunt expandate de compilator in expresii macro, deci in acel ocazie trebuie recunoscut corpul functiei, atat ca forma, cat si din punct de vedere al continutului, fapt greu de realizat in cazul in care ele ar contine structuri repetitive.
Exemplu:
// utilizarea functiilor inline ca functii membre ale unei clase
# include <iostream>
class A{
int u,v;
public:
void init(int k, int l);
void afis( );
};
inline void A::init(int k, int l){u=k; v=l; }
inline void A::afis( ){cout<<u<<" "<<v<<"\n";}
void main( )
{
A x;
x.init(7,12);
x.afis( );
}
In acest exemplu, se observa cum se pot utiliza functiile inline ca functii membre ale unei clase.

Aplicatie:
Sa se implementeze o clasa „sir“ care sa permita efectuarea unor operatii cu siruri, ca: initializare, copiere, atribuirea unui sir unui alt sir, afisarea lor.
Se vor utiliza constructori, destructor, functii inline.

#include <iostream>
#include<conio>
#include<string>
class sir
{
char *ps;
int lg;
public:
sir(char*s);
sir(int nr_car=30);
sir(const sir&);
~sir();
int ret_lg();
void afis();
};
sir::sir(char*s)
{
lg=strlen(s);
ps=new char[lg+1];
strcpy(ps,s);
}
sir::sir(int dim)
{
lg=dim;
ps=new char[lg+1];
*ps='\0';
}
sir::sir(const sir&s)
{
lg=s.lg;
ps=new char[lg+1];
strcpy(ps,s.ps);
}
sir::~sir()
{
delete ps;
}
inline int sir::ret_lg()
{return lg;}
inline void sir::afis( )
{
cout<<ps;
cout<<"\n";
}

void main( )
{
sir s_1("C++ este o extensie a lui C");
sir s_2 ("C++ este un limbaj orientat pe obiect");
sir s_3("Se invata in anul II");
sir s_4=s_1;
cout<<"s_1:"<<"\n";
cout<<s_1.ret_lg( )<<"\n";
s_1.afis( );
cout<<"s_2:"<<"\n";
cout<<s_2.ret_lg( )<<"\n";
s_2.afis( );
cout<<"s_3:"<<"\n";
cout<<s_3.ret_lg( )<<"\n";
s_3.afis( );
cout<<"s_4:"<<"\n";
cout<<s_4.ret_lg( )<<"\n";
s_4.afis( );
}
Aplicatie:
Sa se scrie un program C++ pentru citirea,validarea,afisarea unei date calendaristice curente si pe cea urmatoare ei. Se vor utiliza functii declarate static si functii inline.
#include<iostream> #ifndef_STDIO.H #include<stdio> #define_STDIO.H #endif enum boolean{false,true};
class data_c
{
int zi,luna,an;
static int min_z,min_l,min_a;
static int max_z,max_l,max_a;
static int tab_zi[13];
static char*tab_luna[13];
static char*min_err;
static char*max_err;
static char*err_dc;
static void afis(char*sir);
static void verif();
public:
boolean valid_dc();
static boolean valid_dc_min();
static boolean valid_dc_max();
boolean an_bisect();
static boolean dc_min_bisect();
static boolean dc_max_bisect();
static boolean var_calend(int z,int l,int a);
data_c();
data_c(int z,int l, int a);
data_c(const data_c&);
int ret_zi();
int ret_luna();
int ret_an();
void afis_dc();
data_c*dat_min();
data_c*dat_max();
void modif_min();
void modif_max();
int cit_dat();
boolean ad_zi(int z);
long dif_dat(data_c*d);
char*den_luna();
int zi_an();
boolean zi_luna(int z,int a);
int nr_zile_luna();
};

int data_c::min_z=1;
int data_c::min_l=1;
int data_c::min_a=1900;
int data_c::max_z=31;
int data_c::max_l=12;
int data_c::max_a=2010;
intdata_c::tab_zi[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
char*data_c::tab_luna[13]={"lunainexist.","ian","feb", "martie","apr","mai","iunie","iulie","aug","sept","oct","nov","dec"};
char*data_c::err_dc="data calendaristica eronata \n";
char*data_c::min_err="data minima eronata \n";
char*data_c::max_err="data maxima eronata \n";
inline int bis(int a){ return a%4==0 && a%100==0 ||a%400==0;}
boolean data_c::var_calend(int z,int l,int a)
{
if(a<1900>2010) return false;
if(a<data_c>data_c::max_a) return false;
if(l<1>12)return false; if(a==data_c::min_a&&l<data_c>data_c::max_l)return false;
if(z<1>tab_zials+(l==2&&bis(a)))return false; if(a==data_c::min_a&&l==data_c::min_l&&z<data_c>data_c::max_z)
return false;
return true;
}
inline void data_c::afis(char*sir)
{cout<<"Se afiseaza sirul_data"<<sir;}
inline boolean data_c::valid_dc()
{
return var_calend(zi,luna,an);
}
inline boolean data_c::valid_dc_min()
{return var_calend(data_c::min_z,data_c::min_l,
data_c::min_a);}
inline boolean data_c::valid_dc_max()
{return var_calend(data_c::max_z,data_c::max_l, data_c::max_a);}
boolean data_c::an_bisect()
{if(bis(an)) return true;
else return false;}
boolean data_c::dc_min_bisect()
{
if(bis(data_c::min_a))return true;
else return false;
}
boolean data_c::dc_max_bisect()
{
if(bis(data_c::max_a))return true;
else return false;
}

void data_c::verif()
{
if(data_c::valid_dc_min()==false)
{
data_c::afis(data_c::min_err);
data_c::min_z=1;
data_c::min_l=1;
data_c::min_a=1900;
}
if(data_c::valid_dc_max()==false)
{
data_c::afis(data_c::max_err);
data_c::max_z=31;
data_c::max_l=12;
data_c::max_a=2010;
}
}
data_c::data_c(int z,int l,int a)
{
data_c::verif();
zi=z;
luna=l;
an=a;
if(valid_dc()==false)
{
afis(data_c::err_dc);
zi=data_c::min_z;
luna=data_c::min_l;
an=data_c::min_a;}
}
inline data_c::data_c()
{data_c::verif();}
data_c::data_c(const data_c &d)
{
zi=d.zi;
luna=d.luna;
an=d.an;
if(valid_dc()==false)
{
afis(data_c::err_dc);
zi=data_c::min_z;
luna=data_c::min_l;
an=data_c::min_a;
}
}
inline int data_c::ret_zi(){return zi;}
inline int data_c::ret_luna(){return luna;}
inline int data_c::ret_an(){return an;}
inline void data_c::afis_dc()
{
cout<<"ziua:"<<zi<<"\t"<<"luna:"<<luna<<"\t"<<"anul:"<<an;
}
data_c*data_c::dat_min()
{
data_c*d_min=new data_c(data_c::min_z,data_c::min_l,data_c::min_a);
return d_min;
}

data_c*data_c::dat_max()
{
data_c*d_max=new data_c(data_c::max_z,data_c::max_l,data_c::max_a);
return d_max;
}
void data_c::modif_min()
{
data_c::min_z=zi;
data_c::min_l=luna;
data_c::min_a=an;
data_c::verif();
}
void data_c::modif_max()
{
data_c::max_z=zi;
data_c::max_l=luna;
data_c::max_a=an;
data_c::verif();
}
int data_c::cit_dat()
{
int i;
for(;;){
for(;;){
cout<<"\n";
cout<<"ZIUA:";
cin>>i;
if(i>0&&i<=31)break;
if(cin.eof()) return 0;
cout<<"Zi eronata \tn";
fflush(stdin); //videaza zona de intrare
}
zi=i;
for(;;){
cout<<"LUNA:";
cin>>i;
if(i>0&&i<=12) break;
if(cin.eof())return 0;
cout<<"Luna eronata \n";
fflush(stdin);
}
luna=i;
for(;;){
cout<<"ANUL:";
cin>>i;
if(i>=1900&&i<=2010) break;
if(cin.eof())return 0;
cout<<"Anul eronat \n";
fflush(stdin);
}
an=i;
if(valid_dc()==true)break;
cout<<"Data calendaristica:";
cout<<zi<<"."<<luna<<"."<<an<<"este eronata";
}
return 1;
}
int data_c::zi_an()
{
int b=bis(an);
int z=zi;
for(int i=1;i<luna>365+b){
cout<<"Ziua:"<<z<<"este eronata \n";
return false;
}
if(a<1900>2010){
cout<<"Anul:"<<a<<"este eronat \n";
return false;
}
int i=1;
do{
int j=data_c::tab_zi[i]+(i==2&&b);
if(z<=j) break;
z-=j;
i++;
}while(1);
zi=z;
luna=i;
an=a;
return valid_dc();
}
inline char*data_c::den_luna()
{returnluna<1>12?data_c::tab_luna[0]:data_c::
tab_luna[luna];
}
boolean data_c::ad_zi(int z)
{
int total_zi=zi_an();
total_zi+=z;
int zile_din_an=365+bis(an);
if(total_zi>=0)
while(total_zi>=zile_din_an)
{
total_zi-=zile_din_an;
an++;
if(an<2010>=zile_din_an)
{
total_zi+=zile_din_an;
an--;
if(an>=1900)
zile_din_an=365+bis(an);
}
total_zi+=zile_din_an;
}
if(total_zi==0){
zi=31;
luna=12;
an--;
return valid_dc();
}
boolean bl=zi_luna(total_zi,an);
return bl;
}
long data_c::dif_dat(data_c*d)
{
long zi_an_1=zi_an();
long zi_an_2=d->zi_an();
long dif_zi=zi_an_1-zi_an_2;
int an_1,an_2;
if(an<d>an)
{
an_1=an;
an_2=d->an;
}
else
{
an_1=d->an;
an_2=an;
}
long dif_zi_an=0;
while(an_1<an_2)
{
int b=bis(an_1);
dif_zi_an+=365+b;
an_1++;
}
if(an<d>an)
dif_zi_an=-dif_zi_an;
return dif_zi+dif_zi_an;
}
void main()
{
for(;;){
data_c data_cit;
if(data_cit.cit_dat()==0) break;
cout<<"ZIUA:"<<data_cit.ret_zi();
cout<<"\n";
cout<<"Luna:"<<data_cit.ret_luna();
cout<<"\n";
cout<<"ANUL:"<<data_cit.ret_an();
cout<<"Verif.data_cit:"; cout<<data_cit.var_calend(data_cit.ret_zi(),
data_cit.ret_luna(),data_cit.ret_an()); data_c data_urm=data_cit; cout<<"\n"; cout<<"ZILE DIN AN:"<<data_cit.zi_an(); cout<<"\n"; cout<<"DENUMIREA LUNII CURENTE: " << data_cit.den_luna();
cout<<"\n";
cout<<"VALIDARE:"<<data_cit.valid_dc();
cout<<"\n";
cout<<"VERIF. DAT_MIN:"<<data_cit.valid_dc_min();
cout<<"\n";
cout<<"VERIF.DAT_MAX:"<<data_cit.valid_dc_max();
cout<<"\n";
cout<<"ZIUA URMATOARE:";
data_urm.ad_zi(1);
cout<<"\n";
data_urm.afis_dc();
}
}
Vezi profilul utilizatorului Trimite mesaj privat
Afiseaza mesajele pentru a le previzualiza:   
Creaza un subiect nou   Raspunde la subiect

Subiectul urmator
Subiectul anterior
Nu puteti crea un subiect nou in acest forum
Nu puteti raspunde in subiectele acestui forum
Nu puteti modifica mesajele proprii din acest forum
Nu puteti sterge mesajele proprii din acest forum
Nu puteti vota in chestionarele din acest forum


Powered by phpBB © 2001, 2002 phpBB Group