| Autor |
Mesaj |
Admin
Administrator

Data inscrierii: 07/Dec/2013
Mesaje: 1103
|
1. Supraincarcarea operatorului [ ].
• Operatorul [ ] este numit subscript sau indice si este util in accesarea elementelor unui tablou (variabile cu indici).
Exemplu:
char teta[30], c;
c=teta[8]; // aici actioneaza operatorul [ ]
• Operatorul [ ] este un operator binar. In "teta[8]", teta reprezinta debutantul operand, iar "8" al doilea operand. Se are in vedere ca "[ ]" este un operator de prioritate maxima. Numele tabloului este interpretat ca „primul operand“, deoarece el se poate utiliza intr-un mod similar cu identificatorul unei variabile simple, adica permite accesul la o data de un tip predefinit. Inițialul operand poate fi chiar o formă cu pointeri a carei valoare reprezinta un pointer.
Exemplu:
int i,j,*p;
………………
// Expresii corecte
p[i] // întâiul operand al operatorului [ ] este un pointer
p[i+j-5] // idem
(p+3)[i*j+7] // primul operand al operatorului [ ] este o expresie cu pointeri
…………………….
Al doilea operand asupra caruia actioneaza operatorul [ ] este de un tip oarecare.
• Expresia de forma id_tablou[exp_ind] este o expresie lvalue, deci se poate afla in porțiunea stanga intr-o atribuire. De aceea, functia operator de supraincarcare a operatorului [ ] pentru soiuri abstracte, trebuie sa fie o functie membra nestatica (ca si in cazul operatorului "="), care returneaza o referinta la elementul selectat prin functia respectiva.
• Nu se poate folosi functie friend pentru supraincarcarea operatorului [ ].
• Sintaxa functiei membra operator de supraincarcare a operatorului [ ], adica a functiei operator[ ]( ) este:
tip id_clasa ::operator[ ](tip_ind....);
sau
tip& id_clasa::operator[ ](tip_ind…){…. }
Functia operator [ ] este o functie membra in care primul operand trebuie sa fie un obiect de tipul clasei din care provine, iar al doilea operand este singurul parametru explicit al functiei de un tip oarecare. Avand in vedere scopul acestui operator, de a asigura inscrierea indecsilor intr-un tablou, adesea este exploatat tipul int pentru acest al doilea operand.
• Daca valoarea returnata de functia operator[ ]( ) este o referinta, atunci ea se poate utiliza atat ca operand drept, cat si ca operand stang al operatorului de atribuire.
O expresie de forma tab[k] este interpretata ca tab.operator[ ](k). In expresia tab[k], tab reprezinta obiectul (o instantiere a clasei id_clasa), iar k, de regula, este o expresie care are tipul tip_indice sau un tip convertibil la acesta. Aceasta inseamna ca valoarea expresiei din operatorul de inscriere este transmisa functiei operator[ ]( ) prin parametrul sau explicit. Pointerul this va indica spre tab, obiectul care a generat apelul.
Exemplu:
class Biblioteca
{
private:
char* nume_autor;
unsigned lung;
public:
Biblioteca(int ap)
{nume_autor=new char[lung=ap];}
~Biblioteca( ){delete [ ] nume_autor;}
void operator=(Biblioteca& c);
char& operator[ ](unsigned k);
// prototipul functiei de supraincarcare a operatorului [ ]
};
char& Biblioteca::operator[ ](unsigned k)
{
if(k>lung-1) k=lung-1;
return nume_autor[k];
// Nu este un apel recursiv. De ce?
// Se returneaza o referinta la un element al tabloului.
• Căci operator[ ]( ) returneaza o referinta catre un element al tabloului, care corespunde indicelui precizat explicit, el se poate folosi in partea stanga a unei asignari, cu scopul de a se putea modifica valoarea elementului respectiv din tablou. Astfel, exista un avantaj cu privire la controlul asupra dimensiunilor unui tablou in C++. Mai exact, implementand o clasa, care contine un astfel de tablou la care se îngăduie accesul, prin functia operator[ ]( ), se pot intercepta indicii din exteriorul limitei considerate.
• Functia operator [ ]( ) supraincarcata poate returna valoarea corespunzatoare valorii parametrului ce reprezinta indicele elementului.
Exemplu:
…………………………..
class pardr
{
int x[3];
public:
pardr(int k,int j,int l)
{ //constructor care initializeaza un tablou
x[0]=k;
x[1]=j;
x[2]=l;
}
int operator[ ](int k){return x[k];}:
// se returneaza valoarea de tip int
};
main( ){
pardr ob(10,15,20);
cout<<ob>
Supraincarcarea operatorului -> se realizeaza printr-o functie membra nestatica. La supraincarcare, operatorul -> este considerat ca operator unar care se aplica operandului care il precede.
• O constructie de forma g->u se va interpreta sub forma (g.operator->( ))->u. De aceea, functia operator->( ), trebuie sa returneze fie un pointer la un obiect ce reprezinta o instantiere a clasei in care opereaza, fie un obiect de un anmit tip pentru care este supraincarcat operatorul ->. Explicatia este urmatoarea: g.operator->( ) reprezinta un apel de functie, iar asupra valorii returnate de catre aceasta functie se va aplica ->u. Ultimul operator -> este fie operatorul standard (cand functia returneaza un pointer), fie tot un operator supraincarcat (cand functia returneaza un obiect).
• In constructia:
obiect->element;
obiect este o instantiere a clasei respective, cel care genereaza apelul. In ceea ce priveste element, el trebuie sa fie un element accesibil in cadrul obiectului returnat de functia operator->( ).
Exemplu:
…………………………….
class A
{
public:
int k;
A*operator->( ){return this;} };
main( )
{
A ob;
ob->k=20;
cout<<ob.k<<" "<<ob>k;
// cele doua forme sunt echivalente
return 0;
}
4. Supraincarcarea operatorului virgula
• Virgula este un operator binar. Operatorul virgula supraincarcat, pentru a actiona intr-un mod similar cu actiunea sa normala, trebuie sa renunte la valoarea din termenul sau stang si sa atribuie valoarea operatiei, termenului din dreapta. Astfel ca intr-o lista, in care virgula este un separator, se va renunta la toti termenii prezenti, mai putin ultimul termen din dreapta.
Exemplu:
class exemplu
{
int x,y;
public:
exemplu( ){ }
exemplu(int l1,int l2)
{
x=l1;
y=l2;
}
void afis( )
{
…………..
}
exemplu operator+(exemplu op2);
exemplu operator ,(exemplu op2);
};
exemplu exemplu::operator ,(exemplu op2)
{
exemplu t;
t.x=op2.x;
t.y=op2.y;
cout<<op2.x<<" "<<op2.y<<"\n";
return t;
}
exemplu exemplu::operator+(exemplu op2)
{
exemplu t;
t.x=op2.x+x;
t.y+op2.y+y;
return t;
}
main( )
{
exemplu ob1(10,30),ob2(10,30), ob3(3,3);
ob2.afis( );
cout<<"\n";
ob2=( ob1+ob1, ob2,ob3);
ob2.afis( );
return 0;
}
Desi se renunta la valorile operanzilor, cu exceptia ultimului operand din dreapta, fiecare expresie va fi executata de compilator, semnaland eventualele erori.
• Operandul din fracțiune dreapta este transmis prin this, iar valoarea sa este eliminata de catre functia operator,( ). Functia va returna valoarea din dreapta operatorului.
5. Concluzii cu privire la utilizarea functiilor operator
• Supraincarcarea unor operatori, care actioneaza asupra unor date de tipuri predefinite, cu susținerea functiilor operator, are ca scop posibilitatea acestora de a actiona si asupra unor obiecte de tip abstract.
• O functie operator poate fi sau nu, functie membra a unei clase. Functiile operator membre au cu un parametru mai putin decat cele nemembre, argumentul ascuns fiind dat de pointerul this.
• La declararea unei functii operator este obligatoriu a se avea in vedere urmatoarele:
1. aritatea operatorului (operator unar sau binar);
2. pozitia ocupata de operator(prefix sau postfix);
3. domeniu de actiune (functie membra sau nu).
Aceste elemente determina numarul si tipul parametrilor functiei operator. Pentru functiile membre primul operand al unui operator binar devine obiectul, care impreuna cu operatorul respectiv, actioneaza asupra celui de al doilea operand. In cazul operatorilor unari, pentru a se deosebi cei prefixati de cei postfixati, la cei postfixati se mai adauga un parametru suplimentar, simuland oarecum modul de actionare al acestora.
• Ca orice functie C++, functiile operator se pot supraincarca.
• Pentru ca functia operator sa actioneze cat mai natural asupra obiectului corespunzator, se utilizeaza referinta ca parametru.
• Exista unele restrictii cu privire la utilizarea functiilor operator:
1. nu este permis a se introduce noi operatori;
2. nu se permite schimbarea aritatii operatorului respectiv;
3. cel putin un parametru al functiei operator trebuie sa fie obiect, sau
functia sa fie membra a unei clase.
4. nu se pot combina operatorii cu scopul de a da nastere la noi operatori;
5. functiile operator pentru operatorii =, [ ], ( ), -> trebuie sa fie functii membre nestatice.
Aplicatie:
Calculati inversa unei matrice patratice de ordin doi, folosind si o supraincarcare a operatorului "( )".
#include<iostream>
#include<conio>
#include<math>
class matrice
{
private:
float matr[2][2];
public:
matrice(){};
matrice(float lin_1[2],float lin_2[2])
{
matr[0][0]=lin_1[0];
matr[0][1]=lin_1[1];
matr[1][0]=lin_2[0];
matr[1][1]=lin_2[1];
}
matrice(float cl_1,float cl_2,float cl_3,float cl_4)
{
matr[0][0]=cl_1;
matr[0][1]=cl_2;
matr[1][0]=cl_3;
matr[1][1]=cl_4;
}
matrice(matrice&m);
~matrice(){}
float&operator()(int i,int j)
{
return matr[i][j];
}
float det();
matrice inversa();
friend istream&operator>>(istream&,matrice&);
friend ostream&operator<<ostream>det()))return*this;
else{
t.matr[0][0]=(1/this->det())*matr[1][1];
t.matr[0][1]=-(1/this->det())*matr[0][1];
t.matr[1][0]=-(1/this->det())*matr[1][0];
t.matr[1][1]=(1/this->det())*matr[0][0];
*this=t;
return *this;
}}
matrice::matrice(matrice&m)
{
int i,j;
for(i=0;i<2;i++)
for(j=0;j<2>>(istream& str,matrice&m)
{
cout<<"\n Dati matricea:";
str>>m.matr[0][0];
str>>m.matr[0][1];
str>>m.matr[1][0];
str>>m.matr[1][1];
return str;
}
ostream&operator<<(ostream&str,matrice m)
{
str<<m.matr[0][0];
str<<' ';
str<<m.matr[0][1];
str<<"\n";
str<<m.matr[1][0];
str<<' ';
str<<m.matr[1][1];
return str;
}
matrice&matrice::operator+(matrice m)
{
matrice t(0,0,0,0);
int i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
t.matr[i][j]=matr[i][j]+m.matr[i][j];
*this=t;
return *this;
}
matrice& matrice::operator-(matrice m)
{
matrice t(0,0,0,0);
int i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
t.matr[i][j]=matr[i][j]-m.matr[i][j];
*this=t;
return *this;
}
matrice&matrice::operator*(matrice m)
{
matrice t(0,0,0,0);
int i,j,k;
for(i=0;i<2;i++)
for(j=0;j<2;j++){
t.matr[i][j]=0;
for(k=0;k<2;k++)
t.matr[i][j]+=matr[i][k]*m.matr[k][j];
}
*this=t;
return *this;
}
void main()
{
matrice a,b,c,d,e,f;
clrscr();
cout<<"\n Adunare de matrice:\n";
cin>>a;
cin>>b;
matrice a_1=a,b_1=b;
cout<<a<<"+"<<"\n"<<b<<"=\n";
c=a+b;
cout<<c;
cout<<"\n Inmultirea de matrice:\n";
cout<<a_1<<"*"<<"\n"<<b_1<<"=\n";
cout<<a_1*b_1;
cout<<"\n Inversa si det:\n";
cin>>a;
cout<<"determinantul="<<a.det();
cout<<"\n Inversa:\n"<<a.inversa();
} |
|
|
|
|
 |
|
|
|
|
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
|