Referat Nr. 3 - Supraincarcarea operatorilor

download Referat Nr. 3 - Supraincarcarea operatorilor

of 49

description

Programarea orientata pe obiecte

Transcript of Referat Nr. 3 - Supraincarcarea operatorilor

  • REFERAT DE LABORATOR Nr. 3

    1

    REFERAT DE LABORATOR NR. 3

    TEMA: Suprancrcarea operatorilor.

    NOIUNI TEORETICE

    Suprancrcarea (supradefinirea, termenul overloading) operatorilor permite atribuirea de noi semnificaii operatorilor uzuali (operatorilor ntlnii pentru tipurile de date predefinite). Aa cum am subliniat n numeroase rnduri, clasa reprezint un tip de date (o mulime de valori pentru care s-a adoptat un anumit mod de reprezentare i o mulime de operaii care pot fi aplicate acestora). Astfel, operatorul + folosete la adunarea a dou date de tip int, float sau double, ns aceluiai operator i se poate atribui semnificaia de alipire a dou obiecte de tipul ir, sau de adunare a dou obiecte de tipul complex, vector sau matrice.

    Prin suprancrcarea operatorilor, operaiile care pot fi executate asupra instanelor(obiectelor) unei clase pot fi folosite ca i n cazul tipurilor de date predefinite.

    Declaraia i definiia unui operator suprancrcat, sunt similare cu declaraiile i definiiile de funcii:

    [] operator ()

    {

    // . . . . corpul funciei

    }

    n situaia n care, pentru o clas, suprancrcarea unui operator unar se realizeaz printr-o funcie membr, aceasta primete ca parametru implicit adresa obiectului curent (pentru care este apelat), adic pointerul cptre obiectul curent (this). n cazul suprancrcrii prin funcii prietene (friend), deoarece acestea nu primesc ca argument implicit pointerul ctre obiectul curent, astfel c funcia va primi un parametru explicit.

    Operatorii binari pot fi supradefinii printr-o funcie membr cu un parametru implicit (pointerul this) si parametru explicit sau printr-o funcie prieten cu doi parametri explicii de tipul clas.

  • REFERAT DE LABORATOR Nr. 3

    2

    1. Restricii la suprancrcarea operatorilor

    Suprancrcarea operatorilor se poate realiza, deci, prin funcii membre sau funcii prietene. Dac suprancrcm acelai operator printr-o metod i printr-o funcie prieten, funcia prieten va avea, ntotdeauna, un parametru n plus fa de metod (deoarece funciei prietene nu i se transmite ca parametru implicit pointerul this).

    Totui, suprancrcarea operatorilor este supus urmtoarelor restricii:

    Se pot suprancrca doar operatorii existeni; nu se pot crea noi operatori. Nu se poate modifica aritatea (numrul de operanzi) operatorilor limbajului

    (operatorii unari nu pot fi supraincrcai ca operatori binari, i invers). Nu se poate modifica precedena i asociativitatea operatorilor. Dei operatorii suprancrcai pstreaz aritatea i precedena operatorilor

    predefinii, ei nu motenesc i comutativitatea acestora. Nu pot fi suprancrcai operatorii . (operatorul selector al unui membru), .*

    (operatorul de defereniere, selecie indirect a unui membru), :: (de rezoluie, de apartenen, scop) i ?: (operatorul condiional).

    Observaii:

    Dac operatorul = (de atribuire) nu este suprancrcat, el are o semnificaie implicit.

    Operatorii , new delete [] -> i de conversie explicit impun restricii suplimentare care vor fi discutate ulterior.

    Funcia operator trebuie s aib cel puin un argument (implicit sau explicit) de tipul clasei pentru care s-a suprancrcat operatorul.

    Se poate atribui unui operator orice semnificaie, ns este de dorit ca noua semnificaie s fie ct mai apropiat de semnificaia natural. De exemplu, pentru adunarea a dou obiecte se poate suprancrca operatorul * , dar este mai natural folosirea operatorului + cu semnificaia de adunare.

    2. Membrii constani ai unei clase

    O clas poate avea metode constante. O metod este declarat constant prin utilizarea modificatorului const n antetul ei, dup lista parametrilor formali. Metodele constante nu modific obiectul pentru care sunt apelate.

    Ca oricror variabile de tip predefinit, i obiectelor de tip definit de utilizator li se poate aplica modificatorul const. Pentru un obiect constant este permis doar apelul metodelor constante, a constructorilor i a destructorilor.

  • REFERAT DE LABORATOR Nr. 3

    3

    3. Suprancrcarea operatorilor insertor i extractor

    Operatorul > se numete operator extractor, deoarece extrage date din stream-ul (fluxul) de intrare.

    n exemplul urmtor, aceti operatori sunt suprancrcai pentru clasa complex, astfel nct s poat fi folosii ca pentru obiectele de tip predefinit.

    Deoarece ntotdeauna operandul stng este de tip istream (cin este obiect predefinit, de tip istream) sau ostream (cout este obiect predefinit, de tip ostream), i nu de tipul introdus prin clas, operatorii > pot fi suprancrcai numai prin funcii prietene. Prototipurile operatorilor sunt:

    Prototipurile funciilor operator > pentru un tip abstract tip, sunt:

    friend ostream &operator (istream &,tip&);

    4. Suprancrcarea operatorului de atribuire =

    n cazul n care operatorul de atribuire nu este suprancrcat explicit, compilatorul genereaz unul implicit (ca n exemplul clasei punct sau segment). n absena unei suprancrcri explicite, operatorul copie valorile datelor membre ale operandului drept n datele membre ale operandului stng.

    Exemplu:

    punct a(8,9), b;

    b=a; /* operator atribuire implicit: zona de memorie ocupata

    de obiectul a se copie, bit cu bit, n zona de memorie ocupat

    de b: b.x=a.x i b.y=a.y */

    Operatorul de atribuire implicit este nesatisfctor n situaiile n care obiectele clasei au ca date membre pointeri, sau n situaiile n care memoria este alocat n mod dinamic.

    O suprancrcare explicit a operatorului (ambii operanzi de tipul clasei) poate fi fcut fie prin metod, fie prin funcie prieten.

    O modalitate de a suprancrca operatorul de atribuire prin metod a clasei, este aceea prin care funcia primete ca parametru implicit operandul stng (pointerul this), ca parametru explicit o referin constant (pentru a nu putea fi modificat acest operand) ctre operandul drept, i returneaz o referin (adresa operandului stng).

    Deasemenea, operatorul binar de atribuire poate fi suprancrcat prin funcie prieten (n acest caz, nu primete parametrul implicit this, deci are doi operanzi).

  • REFERAT DE LABORATOR Nr. 3

    4

    Deoarece ntotdeauna operandul stng al operatorului de atribuire este de tipul clasei pentru care se suprancarc, este preferabil ca suprancrcarea s se realizeze prin metod a clasei.

    Reamintim c asociativitatea operatorului este de la dreapta la stnga. Operatorul poate apare n expresii de forma: a=b=c=d;

    5. Suprancrcarea operatorului de indexare [ ]

    Operatorul de indexare este un operator binar, utilizat sub forma:

    []

    S considerm clasa vector, definit astfel:

    class vector{

    private:

    int nrcomp; //nr. componente

    double *tabcomp; //tabloul componentelor;

    //adresa de inceput

    public:

    double &operator[](int);

    }

    Pentru tipul abstract vector, operatorul de indexare poate fi supradefinit, astfel nct s permit accesarea elementului de indice n. n acest caz, operatorul de indexare se poate supradefini printr-o funcie membr a clasei (deoarece operandul stng este de tipul clasei), i poate fi folosit sub forma: v[n] (unde v este obiect al clasei vector; n-expresie ntreag).

    Expresia v[n] este echivalent cu v.operator[ ](n) (apelul explicit al funciei operator []). Transferul parametrului ctre funcia care suprancarc operatorul se poate face prin valoare sau prin referin. n mod obligatoriu, funcia trebuie s returneze referina ctre elementul aflat pe poziia n (pentru a permite eventualele modificri ale elementului, deoarece vector[n] este lvalue).

    Pentru un tip abstract, prototipul funciei membre care supradefinete operatorul de indexare este (const protejeaz argumentul la modificrile accidentale):

    & ::operator [ ] (const int);

    n cazul n care operatorul se suprancarc printr-o funcie prieten, prototipul funciei este:

    & operator [ ] (, const int);

  • REFERAT DE LABORATOR Nr. 3

    5

    6. Suprancrcarea operatorilor new i delete

    Avantajul alocrii dinamice a memoriei i a eliberrii acesteia cu ajutorul operatorilor new i delete, fa de utilizarea funciilor malloc, calloc sau free, const n faptul c operatorii aloc (elibereaz) memorie pentru obiecte, date de tip abstract. Acest lucru este posibil deoarece aceti operatori au o suprancrcare global, standard.

    n cazul n care suprancrcarea standard este insuficient, utilizatorul poate suprancrca operatorii prin metode (implicit!) statice.

    Pentru operatorul new, funcia membr care suprancarc operatorul new are prototipul:

    void * ::operator new (size_t );

    Funcia returneaz un pointer generic a crui valoare este adresa de nceput a zonei de memorie alocate dinamic. Tipul size_t este definit n stdlib.h. La aplicarea operatorului, nu se indic nici o valoare pentru parametrul lungime (mrimea zonei de memorie necesare obiectului pentru care se aloc dinamic memorie), deoarece compilatorul o determin, automat.

    Modul de utilizare al operatorului new:

    * = new ;

    Sau: * = new (, , );

    Aplicarea operatorului new supradefinit de utilizator determin, automat, apelul constructorului corespunztor clasei, sau al constructorului implicit. n a doua form, la alocarea dinamic a memoriei apar i parametrii constructorului (p1, p2, p3).

    Operatorul delete se supradefinete printr-o funcie membr cu prototipul:

    void ::operator delete (void *);

    La aplicarea operatorului delete se apeleaz, automat, destructorul clasei.

    7. Suprancrcarea operatorului ( )

    Operatorul apel de funcie, utilizat sub forma

    ()

    poate fi interpretat ca o operaie binar, avnd ca operand stng nume, iar ca operand drept lista_param_efectivi. Suprancrcarea acestui operator binar, nestatic, va permite utilizarea sub forma: a (b, ), sau (apelul explicit): a.operator() (b, ).

  • REFERAT DE LABORATOR Nr. 3

    6

    Avantajele unui astfel de operator sunt:

    Evaluarea i verificarea listei de argumente n mod similar unei funcii obinuite; Mecanismului de apel: dei operatorul este binar, cel de-al doilea operand fiind o

    list de argumente (chiar vid), funcia operator poate avea orici parametri.

    n cazul n care numele funciei este un pointer ctre o anumit funcie (vezi pointeri ctre funcii), apelul funciei se realizeaz prin:

    (*) ();

    Funcia care suprancarc operatorul trebuie s fie metod nestatic. Suprancrcarea operatorului ( ) se utilizeaz n mod frecvent la definirea aa-numitului iterator. Iteratorii se utilizeaz n legtur cu tipuri abstracte de date, care conin colecii de elemente (liste, arbori, tabele de dispersie, etc.). Pe lng protecia datelor, iteratorii ofer un mijloc simplu de acces la elementele unei colecii (traversarea unei coleciei), fr a intra n detaliile legate de implementarea coleciei (independen a utilizrii unei colecii i implementrii unei colecii). n principiu, un iterator se implementeaz printr-o clas ataat unui tip abstract care conine o colecie de elemente.

    8. Suprancrcarea operatorului ->

    Suprancrcarea operatorului unar -> (de selecie indirect, prin intermediul pointerului) se realizeaz printr-o metod nestatic. Expresia obiect -> expresie va fi interpretat ca (obiect.operator->())->expresie. De aceea, funcia care suprancarc operatorul trebuie s returneze fie un pointer la un obiect al clasei, fie un obiect de un tip pentru care este supradefinit operatorul ->.

    9. Conversii

    Exist urmtoarele tipuri de conversii:

    Conversii implicite; Conversii explicite.

    Conversiile implicite au loc n urmtoarele situaii:

    n cazul aplicrii operatorului de atribuire: operandul drept este convertit la tipul operandului stng.

    La apelul unei funcii: Dac tipul parametrilor efectivi (de apel) difer de tipul parametrilor formali, se ncearc conversia tipului parametrilor efectivi la tipul parametrilor formali.

  • REFERAT DE LABORATOR Nr. 3

    7

    La revenirea dintr-o funcie: Dac funcia returneaz o valoare n programul apelant, la ntlnirea instruciunii return expresie; se ncearc conversia tipului expresiei la tipul specificat n antetul funciei.

    Conversiile explicite pot fi :

    a) tip_predefinit_1 -> tip_predefinit_2 b) tip_predefinit -> tip_definit_de_utilizator (clas) c) clas -> tip_predefinit d) clas_1 -> clas_2

    Conversii din tip predefinit1 n tip predefinit2

    Pentru realizarea unor astfel de conversii, se folosete operatorul unar de conversie explicit (cast), de forma:

    ()

    Conversii din tip predefinit n clas

    Astfel de conversii se pot realiza att implicit, ct i explicit, n cazul n care pentru clasa respectiv exist un constructor cu parametri implicii, de tipul predefinit.

    Conversii din clas n tip predefinit

    Acest tip de conversie se realizeaz printr-un operator special (cast) care convertete obiectul din clas la tipul predefinit. Operatorul de conversie explicit se suprancarc printr-o funcie membr nestatic.

    :: operator ( );

    La apelarea operatorului se folosete una din construciile:

    ();

    ();

    Conversii din clas1 n clas2

    Conversia din tip_abstract_1 n tip_abstract_2 (din clas1 n clas2), se realizeaz cu ajutorul unui constructor al clasei2, care primete ca parametri obiecte din clasa1.

  • REFERAT DE LABORATOR Nr. 3

    8

    PROBLEME REZOLVATE

    1. S se defineasc tipul de date complex, cu datele membru parte real (re) i parte imaginar (im). Pentru tipul de date complex s se defineasc un constructor, un constructor de copiere i un destructor.

    Operaiile care pot fi realizate asupra datelor de acest tip, vor fi:

    calculul modulului unui complex functia modul( ); calculul argumentului unui complex functia arg( ); adunarea a dou numere complexe, precum si adunarea unui complex cu o

    valoare real, realizate prin suprancrcarea operatorului +; diferena a dou numere complexe, realizat prin suprancrcarea operatorului -; produsul a dou numere complexe, realizat prin suprancrcarea operatorului *; negativarea, respectiv pozitivarea unui numr complex, realizate prin

    suprancrcarea operatorilor unari -, respectiv +; suprancrcarea operatorului =; suprancrcarea operatorilor compui +=, -=, *= i /=; incrementarea prii reale, n form prefixat i postfixat, realizat prin

    suprancrcarea operatorului ++; decrementarea prii reale n form prefixat, realizat prin suprancrcarea

    operatorului --; testarea egalitii i a inegalitii dintre dou numere complexe, realizate prin

    suprancrcarea operatorilor ==, respectiv !=; citirea de la tastatur, respectiv afiarea pe ecran a unui numr complex, realizate

    prin suprancrcarea operatorilor extractor >>, respectiv insertor

  • REFERAT DE LABORATOR Nr. 3

    9

    // real + complex

    friend complex operator +(const complex&,const double);

    // complex + double

    complex operator - (const complex &) const;

    complex operator *(const complex ) const;

    complex operator + () const; //operator + unar; metoda constanta

    complex operator - () const; //operator - unar

    complex &operator=(const complex &);

    complex & operator += (const complex &z);

    complex operator += (const double);

    complex operator -= (const complex&);

    complex & operator /= (const complex &z);

    complex & operator ++ (); //forma prefixata

    complex operator ++ (int); //forma postfixata

    complex operator--(); //decrementarea partii reale

    int operator == (complex &z);

    //compara doi complecsi si returneaza 1 n caz de egalitate

    friend int operator != (complex &, complex &);

    //compara doi complecsi si returneaza 1 n caz ca sunt diferiti

    friend ostream& operator > (istream &,complex&);

    //operator citire complex

    };

    inline complex::complex(double r,double i)

    {

    re=r; im=i;

    }

    complex::complex(const complex & z)

    {

    re=z.re; im=z.im;

    }

    inline double complex::modul()

    {

    return sqrt(re*re+im*im);

    }

    double complex::arg()

    {

    double a;

    if (re==0 && im==0)

    return 0.0;

    if (im==0)

    if (re>0)

    return 0.0;

    else

    return M_PI;

    if (re==0)

    if (im==0)

    return M_PI/2;

    else

    return (3*M_PI)/2;

    a=atan(im/re);

    if (re

  • REFERAT DE LABORATOR Nr. 3

    10

    return M_PI+a;

    if (im

  • REFERAT DE LABORATOR Nr. 3

    11

    return *this;

    }

    complex complex::operator+=(const double d)

    {

    re += d;

    return *this;

    }

    complex complex::operator-=(const complex &x)

    {

    re -= x.re;

    im -= x.im;

    return *this;

    }

    complex &complex::operator /= (const complex &z)

    {

    double numitor=z.re*z.re+z.im*z.im;

    double re1=(double)(re*z.re+im*z.im)/numitor;

    double im1=(double)(im*z.re-re*z.im)/numitor;

    re=re1; im=im1;

    return *this;

    }

    complex & complex::operator++() //forma prefixata

    {

    re++;

    return *this;

    }

    complex complex::operator ++ (int) //forma postfixata

    {

    complex z=*this;

    re++;

    return z;

    }

    complex complex::operator--()

    {

    re--;

    return *this;

    }

    int complex::operator==(complex &x)

    {

    return re==x.re && im==x.im;

    }

    int operator!=(complex &x, complex &y)

    {

    return !(x.re==y.re && x.im==y.im);

    }

    ostream &operator

  • REFERAT DE LABORATOR Nr. 3

    12

    istream &operator>>(istream &tastatura, complex &z)

    {

    cout > z.re;

    cout > z.im;

    return tastatura;

    }

    Dup definirea tipului de date complex, vom realiza un fiier de test n care vom testa operaiile pe care le putem face asupra numerelor complexe.

    //Fiierul TestComplex.cpp

    #include "Complex.cpp"

    #include

    int main()

    {

    complex a(2,3), b(1,1), c, d;

    cout

  • REFERAT DE LABORATOR Nr. 3

    13

    cout

  • REFERAT DE LABORATOR Nr. 3

    14

    2. n exemplul urmtor se implementeaz clasa fracie. Ea are ca date membre private nrt i nmt (numrtorul i numitorul). Tot ca metod privat este definit metoda

    simplifica(), metod care simplific o fracie pentru evitarea unor calcule cu numere

    mari. Funcia cmmdc (care implementeaz algoritmul lui Euclid pentru aflarea celui mai

    mare divizor comun a dou numere) nu este nici funcie membr a clasei fracie, nici funcie

    prieten. Ea este apelat de funcia simplifica.

    Ca metode publice sunt definite: un constructor, un destructor, funcia numarator care returneaz valoarea datei membre nrt, funcia numitor care returneaz valoarea datei membre nmt, funcia valoare care returneaz valoarea real obinut prin mprirea numrtorului la numitor.

    Se suprancarc operatorii +, -, *, / prin funcii prietene ale clasei fractie. Semnificaia dat este cea de realizare a operaiilor de adunare, scdere, nmulire i mprire a obiectelor din clasa fracie.

    Se suprancarc operatorii +=, -=, *=, /= prin funcii membre ale clasei fractie.

    Se suprancarc operatorii extractor >> i insertor

  • REFERAT DE LABORATOR Nr. 3

    15

    //Fiierul Fractie.cpp

    #include

    using namespace std;

    class fractie

    {

    int nrt, nmt; // numarator,numitor

    void simplifica(); //metoda de simplificare a fractiei

    public:

    fractie(int nrti=0, int nmti=1); //constructor cu parametri impliciti

    ~fractie() {}; //destructor

    int numarator() {return nrt;}

    int numitor() {return nmt;}

    double valoare() {return (double)nrt/(double)nmt;}

    friend fractie operator+(const fractie&, const fractie&);

    friend fractie operator-(const fractie&, const fractie&);

    friend fractie operator*(const fractie&, const fractie&);

    friend fractie operator/(const fractie&, const fractie&);

    fractie& operator +=(const fractie&);

    fractie& operator -=(const fractie&);

    fractie& operator *=(const fractie&);

    fractie& operator /=(const fractie&);

    friend ostream& operator (istream &, fractie &);

    };

    int cmmdc(int x,int y) //calculeaza si returneaza cmmdc pentru x, y

    {

    int z;

    if (x==0 || y==1)

    return 1;

    if (x

  • REFERAT DE LABORATOR Nr. 3

    16

    if (nmt>1)

    {

    cd=cmmdc(nrt,nmt);

    if (cd>1)

    {

    nrt/=cd;

    nmt/=cd;

    }

    }

    }

    fractie::fractie(int nri, int nmi)

    {

    nrt=nri; nmt=nmi;

    simplifica();

    }

    fractie operator +(const fractie &f1, const fractie &f2)

    {

    int dc;

    fractie f;

    dc=cmmdc(f1.nmt,f2.nmt);

    f.nmt=(f1.nmt/dc)*f2.nmt;

    f.nrt=f1.nrt*(f2.nmt/dc)+f2.nrt*(f1.nmt/dc);

    f.simplifica();

    return f;

    }

    fractie operator -(const fractie &f1, const fractie &f2)

    {

    int dc;

    fractie f;

    dc=cmmdc(f1.nmt,f2.nmt);

    f.nmt=(f1.nmt/dc)*f2.nmt;

    f.nrt=f1.nrt*(f2.nmt/dc) - f2.nrt*(f1.nmt/dc);

    f.simplifica();

    return f;

    }

    fractie operator * (const fractie &f11, const fractie &f22)

    {

    int dc;

    fractie f, f1=f11, f2=f22;

    dc=cmmdc(f1.nrt,f2.nmt);

    if (dc>1)

    {

    f1.nrt/=dc;

    f2.nmt/=dc;

    }

    dc=cmmdc(f2.nrt,f1.nmt);

    if (dc>1)

    {

    f2.nrt/=dc;

    f1.nmt/=dc;

    }

    f.nrt=f1.nrt*f2.nrt;

    f.nmt=f1.nmt*f2.nmt;

    return f;

    }

    fractie operator / (const fractie & f11, const fractie & f22)

    {

    int dc;

    fractie f, f1=f11, f2=f22;

  • REFERAT DE LABORATOR Nr. 3

    17

    dc=cmmdc(f1.nrt,f2.nrt);

    if (dc>1)

    {

    f1.nrt/=dc;

    f2.nrt/=dc;

    }

    dc=cmmdc(f2.nmt,f1.nmt);

    if (dc>1)

    {

    f2.nmt/=dc;

    f1.nmt/=dc;

    }

    f.nrt=f1.nrt*f2.nmt;

    f.nmt=f1.nmt*f2.nrt;

    return f;

    }

    fractie& fractie::operator+=(const fractie &f1)

    {

    int dc=cmmdc(nmt,f1.nmt);

    nmt=(nmt/dc)*f1.nmt;

    nrt=nrt*(f1.nmt/dc)+f1.nrt*(nmt/dc);

    simplifica();

    return *this;

    }

    fractie& fractie::operator-=(const fractie &f1)

    {

    int dc=cmmdc(nmt,f1.nmt);

    nmt=(nmt/dc)*f1.nmt;

    nrt=nrt*(f1.nmt/dc)-f1.nrt*(nmt/dc);

    simplifica();

    return *this;

    }

    fractie& fractie::operator *=(const fractie &f11)

    {

    fractie f1=f11;

    int dc; dc=cmmdc(nrt,f1.nmt);

    if (dc>1)

    {

    nrt/=dc;

    f1.nmt/=dc;

    }

    dc=cmmdc(f1.nrt,nmt);

    if (dc>1)

    {

    f1.nrt/=dc;

    nmt/=dc;

    }

    nrt=nrt*f1.nrt;

    nmt=nmt*f1.nmt;

    simplifica();

    return *this;

    }

    fractie& fractie::operator /=(const fractie &f11)

    {

    fractie f1=f11;

    int dc; dc=cmmdc(nrt,f1.nrt);

    if (dc>1)

    {

    nrt/=dc;

    f1.nrt/=dc;

  • REFERAT DE LABORATOR Nr. 3

    18

    }

    dc=cmmdc(f1.nmt,nmt);

    if (dc>1)

    {

    f1.nmt/=dc;

    nmt/=dc;

    }

    nrt=nrt*f1.nmt;

    nmt=nmt*f1.nrt;

    return *this;

    }

    ostream& operator

  • REFERAT DE LABORATOR Nr. 3

    19

    f1/=f;

    cout

  • REFERAT DE LABORATOR Nr. 3

    20

    3. Se definete clasa vector, care are ca date membre (private):

    int nrcomp; - numrul elementelor vectorului

    int err; - indice de eroare

    double *tabcomp; - adresa de nceput a tabloului componentelor

    Metode:

    vector(int nrc=0); - Constructor iniializare cu parametru implicit: numr elemente 0. Creaz dinamic un vector de elemente reale (double) i iniializeaz elementele cu valoarea 0.

    vector(const vector&); - Constructor de copiere: Pe baza vectorului primit ca argument, creaz un nou vector (de aceeai dimensiune, cu aceleai valori ale componentelor).

    virtual ~vector(); - Destructor: elibereaz memoria alocat dinamic la crearea unui obiect din clasa vector.

    int dimens() const; - Returneaz dimensiunea (numrul elementelor) pentru obiectul curent.

    double &operator[](int); - Suprancarca operatorul de indexare [] prin funcie membr (metod). Returneaz referina ctre elementul cu numrul de ordine indicat ca argument.

    vector &operator=(const vector&); - Suprancarcarea operatorului de atribuire printr-o funcie membr. A fost necesar suprancarcarea operatorului de atribuire datorit faptului c aceast clas conine pointeri ctre datele membre.

    int nrerori() const; - Metod constant (nu poate modifica obiectul curent) care returneaz valoarea datei membre err;

    void anulari(); - Metoda care anuleaz indicele de eroare.

    int comparare(const vector&) const; - Metoda constant care compar obiectul curent (operand stng, argument implicit) cu obiectul primit ca parametru (tot vector). Returneaz o valoare ntreag, care este: 2 dac vectorii au numr de componente diferit; 0 dac obiectul curent are 0 elemente sau dac vectorii comparai au aceleai elemente; 1 dac vectorii au cel puin un element diferit. Metoda nu modific operandul stng. Mod de apelare:

    a.comparare(b); //(unde a, b vectori).

    friend int prodscal(const vector& v1,const vector& v2,

    double& p); - Funcie prieten a clasei vector care calculeaz i returneaz valoarea produsului scalar pentru vectorii v1 i v2, transmii ca argumente:

    [ ] [ ]

    friend int suma(const vector& v1, const vector& v2,

    vector& v); - Funcie prieten care calculeaz vectorul sum v: [ ] [ ] [ ]

    Returneaz o valoare ntreag: 1 dac numrul de elemente din v1 este diferit de numrul elementelor din v2; 0 dac v2 are 0 elemente, sau dac s-a calculat suma; 3 dac v are 0 elemente

    friend int diferenta(const vector&v1,const vector&

    v2,vector& v); - Funcie prieten care calculeaz vectorul diferen v: [ ] [ ] [ ]

  • REFERAT DE LABORATOR Nr. 3

    21

    Returneaz o valoare ntreag: 1 dac numrul de elemente din v1 este diferit de de numrul elementelor din v2; 0 dac v2 are 0 elemente, sau dac s-a calculat diferena; 3 dac v are 0 elemente.

    friend ostream &operator

  • REFERAT DE LABORATOR Nr. 3

    22

    public:

    vector(int nrc=0); //constructor initializare pentru un vector vid

    vector(const vector&); //constr. copiere

    ~vector(); //destructor

    int dimens() const { return nrcomp; } //metoda constanta

    double &operator[](int); //supraincarcare operator indexare

    vector& operator=(vector); //supraincarcare operator de atribuire

    int nrerori() const { return err; }

    void anulari() { err=0; }

    int operator ==(const vector&) const; //compara 2 vectori

    friend ostream& operator

  • REFERAT DE LABORATOR Nr. 3

    23

    else

    for(int k=0;k

  • REFERAT DE LABORATOR Nr. 3

    24

    err=v.err;

    for (int k=0;k

  • REFERAT DE LABORATOR Nr. 3

    25

    vector &vector::operator+=(const vector &b)

    {

    if (nrcomp!=b.nrcomp)

    err++;

    else if (nrcomp>0)

    for (int k=0;k0)

    for (int k=0;ka)

    i++;

    while (tabcomp[j]

  • REFERAT DE LABORATOR Nr. 3

    26

    return 0;

    quicksort(0,nrcomp-1,modsort);

    return 0;

    }

    Dup definirea tipului de date vector, vom realiza un fiier de test n care vom testa operaiile pe care le putem face asupra vectorilor.

    //Fiierul TestVector.cpp

    #include "Vector.cpp"

    int main()

    {

    int nr_elem;

    cout > nr_elem;

    vector v1(nr_elem), v2;

    v2 = vector(nr_elem);

    cout

  • REFERAT DE LABORATOR Nr. 3

    27

    4. Fie clasa Sir, pentru care se suprancarc operatorul de indexare printr-o funcie membr. Funcia returneaz o referin ctre caracterul de indice n (transmis ca argument explicit).

    #include

    #include

    using namespace std;

    class Sir {

    char *sptr;

    public:

    Sir(char *);

    ~Sir() { delete sptr; }

    void afisare() { cout

  • REFERAT DE LABORATOR Nr. 3

    28

    cout

  • REFERAT DE LABORATOR Nr. 3

    29

    sir &operator+=(const sir&); operator suprancarcat prin funcie

    membr care realizeaz concatenarea obiectului curent (operandul implicit, de

    tip ir) cu obiectul de tip ir primit ca parametru.

    friend sir operator+(const sir& s1, const sir& s2);

    suprancarc operatorul de adunare printro funcie prieten. Acesta

    concateneaz obiectele de tip ir primite ca parametri. Returneaz irul obinut

    n urma concatenrii.

    friend ostream &operator(istream &, sir&); suprancarc

    operatorul extractor printro funcie prieten a clasei ir.

    //Fiierul Sirul.cpp

    #include

    #include

    using namespace std;

    class sir

    {

    int lung; //lungimea propriu-zisa, fara terminator

    char *sirul; //adresa inceput sir (sirul-pointer catre inceput sir)

    public:

    sir(); //constructor vid: construieste un sir vid

    sir (char *); //constructor initializare primeste ca argument

    //un sir standard

    sir(const sir&); // constructor copiere: primeste ca argument

    //o referinta catre un obiect din clasa sir si

    //trebuie sa faca o copiere

    ~sir(); //destructor

    int lungime(); //metoda care returneaza numarul de caractere

    //din componenta sirului

    const char *continut(); //metoda inline-returneaza continutul

    //sirului curent

    sir &operator=(const sir&); //supraincarcare operator atribuire

    //(necesar datorita faptului ca, in cls sir, exista un

    //pointer catre data membra "sirul" supraincarcat prin functie

    //membra, deoarece intotdeauna membrul stang este un obiect

    //din clasa sir

    sir &operator+=(const sir&);

    //concateneaza argumentul primit la sirul curent

    friend sir operator+(const sir&, const sir&);

    //concateneaza argumentele intr-un sir nou

    friend ostream &operator(istream &,sir&);

    //supraincarcare operator extractor

    };

    sir::sir()

    {

    sirul = 0;

    lung = 0;

    }

  • REFERAT DE LABORATOR Nr. 3

    30

    sir::sir(char *s)

    {

    lung = strlen(s);

    if (lung>0)

    {

    sirul = new char[lung+1];

    if (sirul != 0)

    strcpy(sirul,s);

    else

    lung = 0;

    }

    else

    sirul = 0;

    }

    sir::sir(const sir &s)

    {

    if (s.lung>0)

    {

    sirul = new char[s.lung+1];

    if (sirul != 0)

    {

    strcpy(sirul,s.sirul);

    lung = s.lung;

    }

    else

    lung = 0;

    }

    else

    {

    lung = 0;

    sirul = 0;

    }

    }

    sir::~sir()

    {

    if (sirul != 0)

    delete sirul;

    }

    int sir::lungime()

    {

    return lung;

    }

    const char *sir::continut()

    {

    return sirul;

    }

    sir &sir::operator=(const sir&s)

    {

    if (sirul != 0)

    delete sirul;

    if (s.lung>0)

    {

    sirul = new char[s.lung+1];

    if (sirul != 0)

    {

    strcpy(sirul,s.sirul);

    lung = s.lung;

    }

  • REFERAT DE LABORATOR Nr. 3

    31

    else

    lung = 0;

    }

    else

    {

    sirul = 0;

    lung = 0;

    }

    return *this;

    }

    sir & sir::operator+=(const sir &s)

    {

    if (s.lung>0)

    {

    char *ps;

    int lung1;

    lung1 = lung + s.lung;

    ps = new char[lung1+1];

    if (ps != 0)

    {

    strcpy(ps,sirul);

    strcat(ps,s.sirul);

    delete sirul;

    sirul = ps;

    lung = lung1;

    }

    }

    return *this;

    }

    sir operator+(const sir &s1, const sir &s2)

    {

    sir s;

    s.lung = s1.lung + s2.lung;

    s.sirul = new char[s.lung+1];

    if (s.sirul != 0)

    {

    if (s1.lung>0)

    strcpy(s.sirul,s1.sirul);

    else

    strcpy(s.sirul,"");

    if (s2.lung>0)

    strcat(s.sirul,s2.sirul);

    }

    else

    {

    s.lung = 0;

    s.sirul = 0;

    }

    return s;

    }

    ostream &operator>s1;

  • REFERAT DE LABORATOR Nr. 3

    32

    s=s1;

    return intr;

    }

    Dup definirea tipului de date sir, vom realiza un fiier de test n care vom testa operaiile pe care le putem face asupra sirurilor.

    //Fiierul TestSirul.cpp

    #include "Sirul.cpp"

    int main()

    {

    const char *p;

    sir s1("SIR INITIALIZAT!"), s2(s1), s3, s4;

    cout

  • REFERAT DE LABORATOR Nr. 3

    33

    6. Se implementeaz clasa matrice. Matricea este privit ca un vector de linii.

    Date membre (protected):

    int Dim1,Dim2; - nr. linii, nr. coloane

    double *tab; - pointer ctre tabloul componentelor

    int err; - indice de eroare

    Metode:

    matrice (int dim1=0, int dim2=0); - Constructor matrice, cu alocare dinamic.

    matrice(const matrice&); - Constructor de copiere

    ~matrice(); - Destructor, cu rolul de a elibera memoria alocat dinamic.

    int pune(int ind1, int ind2, double elem); - Iniializeaz elementul de indici (ind1, ind2) cu valoarea transmis ca argument (al treilea parametru). ntoarce valoarea ntreag 1 dac indicii sunt incoreci.

    int dim1()const; - Metod constant care returneaz numrul de linii.

    int dim2() const; - Metod constant care returneaz numrul de coloane.

    int nrerori() const; - Metod constant (nu poate modifica obiectul curent), returneaz valoarea datei membre err;

    void anulari(); - Metod care anuleaz indicele de eroare.

    double elem(int ind1, int ind2) const; - Metod constant care returneaz valoarea elementuluilui de indici (ind1,ind2).

    friend ostream &operator

  • REFERAT DE LABORATOR Nr. 3

    34

    matrice &operator=(const matrice&); - Suprancrcarea operatorului de atribuire printr-o funcie membr. A fost necesar suprancrcarea operatorului de atribuire datorit faptului c aceast clas conine pointeri ctre datele membre.

    int dimtab()const; - Metod constant care returneaz numrul de elemente din matrice (Dim1*Dim2).

    virtual int comparare(const matrice&) const; - Metod constant care compar obiectul curent cu obiectul primit ca argument.

    matrice operator+(const matrice&) const; - Operator de adunare suprancrcat prin metod constant care returneaz o matrice (ntoarce o copie care poate fi utilizat n programul apelant) reprezentnd suma dintre obiectul curent i cel primit ca argument.

    matrice operator-(const matrice&) const; - Operator de scdere suprancrcat prin metod constant care returneaz o matrice (ntoarce o copie care poate fi utilizat n programul apelant) reprezentnd suma dintre obiectul curent i cel primit ca argument.

    matrice &operator+=(const matrice&); - Operator suprancrcat prin metod, deoarece ntotdeauna operandul stng este de tipul matrice. Este folosit n expresii cum ar fi: a+=b (a i b de tipul matrice).

    matrice &operator-=(const matrice&); - Operatorul -= suprancrcat prin metod, deoarece ntotdeauna operandul stng este de tipul matrice. Este folosit n expresii cum ar fi: a-=b (a i b de tipul matrice).

    friend matrice operator*(double, const matrice&); -

    Operator suprancrcat prin funcie prieten, pentru a putea fi utilizat n expresii n*M, unde n este de tip real sau ntreg i M de tipul matrice.

    matrice operator*(const matrice&) const; - Operator suprancrcat prin funcie membr, care nmulete obiectul curent (tip matrice) cu obiectul primit ca argument (tot tip matrice).

    int indtab(int i,int j) const; - Metod care returneaz indicele din tabloul unidimensional (matricea este privit ca un tablou unidimensional, cu elementele memorate ntr-un tablou unidimensional, nti elementele primei linii, n continuare elementele celei de-a doua linii, etc.) pentru elementul[i][j].

    int erind(int, int) const; - Metod care testeaz eventualele erori de indexare.

    matrice transp() const; - Metoda calculeaz i returneaz matricea transpus pentru obiectul curent. Nu modific obiectul curent.

    double operator ( ) (int i, int j); - Suprancrcarea operatorului ( ) prin metod a clasei care returneaz valoarea elementului de indici i i j pentru obiectul curent, sau 0 n cazul n care apare o eroare de indexare (vezi i metoda elem). Apelul metodei elem: A.elem(1, 3) este echivalent cu apelul A(1, 3).

    //Fiierul Matrice.cpp

    #include

    using namespace std;

    class matrice{

    int Dim1,Dim2;

    double *tab;

    int err;

  • REFERAT DE LABORATOR Nr. 3

    35

    public:

    matrice (int dim1=0,int dim2=0);

    matrice(const matrice&);

    ~matrice();

    int pune(int ind1, int ind2, double elem);

    //pune elementul elem pe pozitia de indici (ind1, ind2)

    //intoarce 1 daca indicii sunt incorecti

    friend ostream &operator

  • REFERAT DE LABORATOR Nr. 3

    36

    }

    }

    }

    matrice::matrice(const matrice &M) //constructor copiere

    {

    err=0; int k, dtab;

    if (M.Dim1

  • REFERAT DE LABORATOR Nr. 3

    37

    {

    for (j=0;j

  • REFERAT DE LABORATOR Nr. 3

    38

    matrice matrice::operator+(const matrice &B) const

    {

    matrice C; int k, dtab;

    if (Dim1!=B.Dim1 || Dim2!=B.Dim2)

    C.err=1;

    else

    {

    dtab=Dim1*Dim2;

    C.tab=new double [dtab];

    if (C.tab==0)

    {

    C.Dim1=0;

    C.Dim2=0;

    C.err=2;

    }

    else

    {

    C.Dim1=Dim1;

    C.Dim2=Dim2;

    if (dtab!=0)

    for (k=0;k

  • REFERAT DE LABORATOR Nr. 3

    39

    tab[k]+=B.tab[k];

    }

    return *this;

    }

    matrice &matrice::operator-=(const matrice &B)

    {

    int dtab;

    if (Dim1!=B.Dim1 || Dim2!=B.Dim2)

    err++;

    else

    {

    dtab=Dim1*Dim2;

    if (dtab!=0)

    for (int k=0;k

  • REFERAT DE LABORATOR Nr. 3

    40

    if (C.tab==0)

    {

    C.err=3;

    return C;

    }

    for (i=0;i

  • REFERAT DE LABORATOR Nr. 3

    41

    cout > nr_elem;

    matrice a(nr_elem, nr_elem), b(nr_elem, nr_elem), c;

    cout

  • REFERAT DE LABORATOR Nr. 3

    42

  • REFERAT DE LABORATOR Nr. 3

    43

  • REFERAT DE LABORATOR Nr. 3

    44

    7. S se urmreasc urmtorul program care ilustreaz conversiile din tip predefinit n clas i din clas n tip predefinit. Pentru clasa fracie, se va suprancrca operatorul de conversie explicit, care s realizeze conversii fracie -> int.

    #include

    using namespace std;

    class fractie

    {

    long nrt, nmt;

    public:

    fractie(int n=0, int m=1) { nrt=n; nmt=m; }

    friend ostream &operator

  • REFERAT DE LABORATOR Nr. 3

    45

    cout

  • REFERAT DE LABORATOR Nr. 3

    46

    class complex

    {

    double re, im;

    public:

    complex (double r=0, double i=0) { re=r; im=i; }

    complex (fractie &f) { re=(double)f.nrt/f.nmt; im=0; }

    // conversie fractie->complex

    operator double() const {return re;}

    //conversie complex->double

    friend ostream &operator

  • REFERAT DE LABORATOR Nr. 3

    47

    n continuare, am introdus capturi de ecran din timpul execuiei programului, pentru a se putea urmri execuia programului de test.

    PROBLEME PROPUSE SPRE REZOLVARE

    1. Fie clasa complex, cu datele membre parte_r i parte_i.

    a) S se suprancarce operatorul + binar care realizeaz operaii de forma d+c, unde d este

    ntreg, c este complex, iar rezultatul complex;

    b) S se suprancarce operatorul de nmulire a dou numere complexe printr-o metod

    membr.

    2. Pentru clasa punct, cu datele membre A (abscisa) i O (ordonata) s se suprancarce operatorii:

    a) unar, care negativeaz valorile abscisei i ordonatei pentru un punct;

    b) Funcie prieten de afiare.

  • REFERAT DE LABORATOR Nr. 3

    48

    3. Pentru clasa complex cu datele membre p_real i p_imag, s se suprancarce operatorii:

    a) ==, care compar 2 complexi, prin metod a clasei;

    b) + binar care realizeaz operaii de forma d+c, unde d este real, c este complex, iar

    rezultatul complex

    4. Pentru clasa complex, cu datele membre pr i pi, s se suprancarce operatorii:

    a) * binar care realizeaz operaii de forma d+c, unde d este real, c este complex, iar

    rezultatul complex;

    b) binar, prin metod (realizeaz operaii de forma C-D, unde C i D sunt complexi).

    5. Pentru clasa fractie cu datele membre numit i numar, s se suprancarce operatorii:

    a) extractor;

    b) != binar, prin metod, care realizeaz operaii de forma f!=r, unde f este de tip fracie i r

    de tip real.

    6. Pentru clasa fracie cu datele membre nm (numitor) i nt (numartor), s se suprancarce operatorii:

    a) ! unar care schimb ntre ele valorile datelor membre;

    b) binar, care relizeaz operaii de forma d-f, unde d este real, iar f fracie.

    7. Fie clasa complex, cu datele membre part_r i part_i.

    a) S se suprancarce operatorul += binar, care realizeaz operaii de forma c1+=c2,

    unde c1 i c2 sunt complexi.

    b) S se implementeze o funcie prieten de afiare a unui complex.

    8. Fie clasa fracie, cu datele membre nm (numitor) si nr (numrtor).

    a) S se suprancarce operatorul != , care realizeaz operaii de forma f != a, unde f

    este fracie, iar a este real, prin metod a clasei;

    b) S se suprancarce operatorul binar, printr-o funcie prieten, astfel ncat s

    realizeze operaii de forma f1-f2, unde f1 si f2 sunt fracii.

    9. Pentru clasa ir, s se suprancarce operatorii:

    a)

  • REFERAT DE LABORATOR Nr. 3

    49

    b) S se suprancarce operatorul ! care transform caracterele din coninutul irului

    din litere mari n litere mici;

    c) S se defineasc destructorul pentru ir;

    d) S se suprancarce operatorul binar I logic (pe cuvnt) care din dou iruri s1 i

    s2, construiete un alt ir, care conine caracterele comune lui s1 si s2;

    e) S se suprancarce operatorul != care testeaz existena unui caracter (dat ca

    argument) ntr-un ir. Dac acel caracter este coninut n ir, se returneaz

    valoarea 1, altfel valoarea 0;

    f) S se suprancarce operatorii relaionali care compar lexicografic coninutul a

    dou iruri;

    g) S se suprancarce operatorul unar care realizeaz conversia tuturor

    caracterelor alfabetice din coninutul unui obiect de tip ir, din litere mari n

    litere mici.

    11. S se defineasc tipul dat calendaristic. Data calendaristic se va introduce sub forma zz/ll/aaaa, fiind validat (se va ine cont de anii biseci). Se vor suprancrca operatorii:

    a) insertor;

    b) extractor;

    c) += (adun la dat un numr de zile);

    d) -= (scade dintr-o dat un numr de zile);

    e) == (compar 2 date);

    f) - (returneaz numrul de zile dintre dou date);

    g) + (adun dou date);

    h) ++ (incrementeaz luna);

    i) -- (decrementeaz luna).

    12. Pentru clasa ir, sa se suprancarce operatorul