Sunteți pe pagina 1din 11

MINISTERUL EDUCAIEI AL REPUBLICII MOLDOVA

Universitatea Tehnic a Moldovei


Facultatea Calculatoare Informatic i Microelectronic
Catedra Automatica i Tehnologii Informaionale

RAPORT
Lucrarea de laborator nr. 3
Disciplina: Programarea n limbajul C++
(Varianta nr. 7)

A efectuat:

st. gr. SI-141


Nemerenco Ecaterina

A verificat:

lector univ.
Lisnic Inga

Chisinau 2015

Tema: Suprancrcarea operatorilor


Scopul lucrrii:

Studierea necesitii suprancrcrii operatorilor;


Studierea sintaxei de definire a operatorilor;
Studierea tipurilor de operatori;
Studierea formelor de suprancrcare;
Noiuni teoretice

Operatorii sunt notaii concise, infixate, pentru operaii matematice uzuale. Limbajul C++, ca orice limbaj de programare
asigur un set de operatori pentru tipurile primitive. n plus, fa de limbajul C, C++ ofer posibilitatea asocierii operatorilor
existeni cu tipurile definite de utilizator . Astfel, prezint interes extinderea operatorilor n aritmetic complex, algebra
matricial, n lucrul cu iruri de caractere, etc. Un operator poate fi privit ca o funcie, n care termenii sunt argumentele funciei
(n lipsa operatorului +, expresia a+b s-ar calcula apelnd funcia aduna(a,b)).
Limbajul C++ introduce urmtorii operatori noi: new i delete- pentru gestiunea memoriei dinamice, operatorul de
rezoluie (::) i operatorii de acces la membri: .* i ->*.

1. Suprancrcare.
Prin suprancrcarea unui operator, acesta este utilizat n contexte diferite, avnd aceeai semnificaie sau o semnificaie
diferit. Astfel operatorul + este suprancrcat pentru adunarea ntregilor i a realilor; operatorul << este suprancrcat cu
semnificaia de deplasare la stnga, dac termenii sunt ntregi sau inserare n flux, dac un termen este un flux de date, iar cellalt
un obiect.
Programatorul poate asocia noi semnificaii operatorilor existeni prin suprancrcarea operatorilor. Vom evita folosirea
termenului redefinire, cruia i vom da o semnificaie diferit, n contextul motenirii.
Anumii operatori pot fi utilizai cu orice tip de termeni (sunt deja suprancrcai global de ctre compilator). Acetia
sunt: new, delete, sizeof, ::, =, &, ->*, .*, ., ->.
Pot fi suprancrcai urmtorii operatori:
+ - * / % ^ & | ~ ! = < >
+= -= *= /= %= ^= &= |= >>= <<= == != <= >=
&& || ++ -- ->* , -> << >> [] ()
new new[] delete delete[]
Nu pot fi suprancrcai operatorii: ::, ., .*, ?:, sizeof.
Setul de operatori ai limbajul C++ nu poate fi extins prin asocierea de semnificaii noi unor caractere, care nu sunt
operatori de exemplu nu putem defini operatorul **).
Prin suprancrcarea unui operator nu i se poate modifica aritatea (astfel operatorul ! este unar i poate fi redefinit
numai ca operator unar. De asemeni asociativitatea i precedena operatorului se menin.
La suprancrcarea unui operator nu se pot specifica argumente cu valori implicite.
Operatorii suprancrcai ntr-o clas sunt motenii n clasele derivate (excepie face operatorul de atribuire =).
Semntura unei funcii n care se suprancarc un operator este:
tip_rezultat operator#(list_argumente);
Modaliti de suprancrcare a operatorilor.
O funcie operator suprancrcat poate fi introdus ca funcie membr (n general nestatic) sau funcie prieten (funcie
nemembr).
Declararea unei funcii membr nestatic specific urmtoarele:
funcia poate accesa partea privat a declaraiei clasei
funcia este n domeniul clasei

funcia trebuie apelat dintr-un obiect


O funcie membr static satisface numai primele dou condiii, n timp ce o funcie prieten a unei clase satisface numai
prima condiie.
O funcie operator avnd ca prim argument un tip primitiv nu poate fi funcie membru.
Funciile care modific reprezentarea unui obiect necesit acces la datele membri, deci trebuie s aparin clasei. Ele sunt
funcii membrecu argumente referine neconstante.
Dac se doresc conversii implicite pentru termenii funciei operator, aceasta va fi funcie nemembr cu argumente
referine constante. Aceste funcii implementeaz operatorii care nu necesit operanzi L-valori (adic se aplic tipurilor
fundamentale). Acetia sunt n general operatorii binari. Necesitatea accesului la reprezentare determin definirea lor ca funcii
prieten.
Operatorii care produc o nou valoare din valorile argumentelor (de exemplu operatorul+) se definesc n afara clasei.
Dac nu sunt necesare conversii de tip, alegerea ntre funcie membru i funcie prieten rmne la latitudinea
programatorului.
O funcie nemembr folosete numai argumente explicite, n timp ce o funcie membr folosete argumentul implicit
this.
Argumentele clase, transmise prin valoare se copiaz n stiv neeconomic. Se prefer n acest caz argumentele referine
constante.
Dac valoarea ntoars de funcie este o referin, atunci aceasta nu poate fi o variabil automatic (local funciei). Ea
nu poate fi nici o variabil static local, deoarece operatorul poate fi folosit de mai multe ori ntr-o expresie. Valoarea de
ntoarcere trebuie s fie alocat n memoria liber (heap) sau s fie preluat dintr-un buffer de obiecte statice.
ntoarcerea unei referine la obiectul modificat se realizeaz prin return *this.
Se caut minimizarea numrului de funcii care au acces la reprezentarea intern a unei clase, prevzndu-se funcii de
acces.
n mod obligatoriu sunt funcii membre: constructorii, destructorii, funciile virtuale, etc.
4. Operatori suprancrcai ca funcii prieten.
Operatorii folosii n mod uzual pot fi unari sau binari. Utilizarea unui operator binar sub forma a#b este interpretat ca
operator#(a,b)
Aadar, un operator binar va fi reprezentat printr-o funcie nemembr cu dou argumente, iar un operator unar, printr-o
funcie nemembr cu un singur argument.
Argumentele se iau clase sau referine constante la clase (pentru o preluare economic, asigurnd protecia datelor)
Operatori suprancrcai ca funcii membri.
Funciilor membru li se transmite un argument implicit (ascuns) this (adresa obiectului, care poate reprezenta primul
termen), motiv pentru care un operator binar poate fi implementat printr-o funcie membru nestatic cu un singur argument
(termenul din dreapta operatorului). a#b este interpretat ca a.operator#(b)
O funcie membru operator unar ca o funcie membru nestatic fr argumente ( #a se interpreteaz ca a.operator#();
pentru operatorul postfixat a# convenia este a.operator#(int) ).

Sarcina Lucrarii:

Varianta 7
) S se creeze clasa Bool variabile logice. S se defineasc operatorii "+" SAU logic, "*" I logic, "^" SAU
EXCLUSIV, ca metode ale clasei, iar operatorii "==" i "!=" ca funcii prietene. Operatorii trebuie s permit
realizarea operaiilor att cu variabilele clasei date, ct i cu variabilele de tip predefinit int. (Dac numrul ntreg este
diferit de zero, se consider c variabila este adevr, altfel fals.)
b) S se creeze clasa String ir, utiliznd memoria dinamic. S se defineasc operatorii "+" adunarea irurilor, "="
i "+=" atribuirea ca funcii prietene. S se defineasc operatorii de comparare: "==", "!=", "<", ">" ca metode ale
clasei. Operatorii trebuie s lucreze att cu String, ct i cu char*. S se defineasc operatorul "[]" de acces la fiecare
simbol n parte. S se suprancarce operatorii "<<" i ">>" pentru ieiri/intrri de obiecte.

Sarcina a:
}
#include <iostream>
using namespace std;
class Bool{
int x;
public:
Bool();
void get();
void show();
Bool operator ||(const Bool&);
Bool operator *(const Bool&);
Bool operator ^(const Bool&);
Bool operator ||(const int);
Bool operator *(const int);
Bool operator ^(const int);
friend bool operator ==(Bool, Bool);
friend bool operator !=(Bool, Bool);
};
Bool::Bool(){
x = 0;
}
void Bool::get()
{
int n;
cin>>n;
if (n==0) { x = 0; }
else if (n == 1){ x = 1; }
else if (n != 0){ x= 1; }
}
void Bool::show()
{
cout << x << endl;
}

Bool Bool::operator ||(const Bool&obj)


{
Bool *sum=new Bool();
if ((x == obj.x) && (obj.x == 0)) {
sum->x=0; }
else if ((x == 1) || (obj.x == 1)) {
sum->x = 1; }
return *sum;
}
Bool Bool::operator ||(const int a)
{
Bool *sum = new Bool();
if ((x == a) && (a == 0)) { sum->x = 0;
}
else if ((x == 1) || (a == 1)) { sum->x
= 1; }
return *sum;

Bool Bool::operator *(const Bool&obj)


{
Bool *prod = new Bool();
if ((x == obj.x) && (obj.x == 1)) {
prod->x = 1; }
else if ((x == 0) || (obj.x == 0)) {
prod->x= 0; }
return *prod;
}
Bool Bool::operator *(const int a)
{
Bool *prod = new Bool();
if ((x == a) && (a == 1)) { prod->x =
1; }
else if ((x == 0) || (a == 0)) { prod>x = 0; }
return *prod;
}
Bool Bool:: operator ^(const Bool&obj)
{
Bool *sum = new Bool();
if ((x == obj.x) && ((obj.x == 1) ||
(obj.x == 0))) { sum->x = 0; }
else if ((x == 1) || (obj.x == 1)) {
sum->x = 1; }
return *sum;
}
Bool Bool:: operator ^(const int a)
{
Bool *sum = new Bool();
if ((x == a) && ((a == 1) || (a== 0)))
{ sum->x = 0; }
else if ((x == 1) || (a == 1)) { sum->x
= 1; }
return *sum;
}
bool operator !=(Bool A, Bool B)
{
bool n;
if (A.x != B.x){ n=true; }
else{ n = false; }
return n;
}
bool operator ==(Bool A, Bool B)
{
bool n;
if (A.x == B.x) { n = true; }
else{ n = false; }
return n;
}
int main()
{
Bool A,B;
Bool *temp=new Bool();
int op;

while (1){
system("cls");
cout << "\n
Meniu" << endl;
cout << "[1] Introducerea
variabelelor logice" << endl;
cout << "[2] Afisarea
variabelelor logice" << endl;
cout << "[3] Operatiunea OR" <<
endl;
cout << "[4] Operatiunea AND" <<
endl;
cout << "[5] Operatirunea XOR"
<< endl;
cout << "[6] Verifica pentru
egalitate" << endl;
cout << "[10] Iesire" << endl;
cin >> op;
switch (op){
case 1: system("cls");
cout << "Introduceti prima
variabila" << endl;
A.get();
cout << "Introduceti adoua
variabila" << endl;
B.get();
cout << "Introducerea a
avut loc cu succes!" << endl;
system("pause");
break;
case 2:
system("cls");
cout << "Variabilele
logice:\n";
A.show();
B.show();
system("pause");
break;
case 3:
system("cls");

*temp = A || B;
cout << " A + B = ";
temp->show();
cout << "\n";
system("pause");
break;
case 4:
system("cls");
*temp = A*B;
cout << " A * B = ";
temp->show();
cout << "\n";
system("pause");
break;
case 5:
system("cls");
*temp = A^B;
cout << " A ^ B = ";
temp->show();
cout << "\n";
system("pause");
break;
case 6:
system("cls");
if (A == B) { cout <<
"Variabilele sunt egale" << endl; }
else if(A != B){ cout <<
"Variabilele nu sunt egale" << endl; }
system("pause");
break;
case 10:
exit(0);
break;
}
}
return 0;
}

Sarcina b:
#include <iostream>

rhs[k] = Ch;
k++;
}

using namespace std;


cout << endl;
class String
{
private:
size_t _Size;
char *_String;
public:
String();
String(const char *Str);
String(const String& Str);
~String();
// Atribuirea sirurilor
String& operator=(const String& Str);
// Concatinarea sisurilor
String& operator+= (const char* Str);
String& operator+= (String& Str);
String& operator+= (char Ch);
String& Copy(const char * s);
String& Copy(String& s);
String& Cat(const char * Str);
String& Cat(char Ch);
String& Cat(String& Str);
size_t Length(void) { return _Size; }
string operator [] (string rhs)
{
int k = 0, x; char Ch;
for (rhs.begin(); k <
rhs.length(); rhs.end())
cout << "[" << rhs[k++] <<
"]";
cout << endl;
k = 0;
for (rhs.begin(); k <
rhs.length(); rhs.end())
cout << "[" << k++ << "]";
cout << endl;
cout << "\nIntroduceti pozitia
unui element x care doriti sa schimbati: ";
cin >> x;
cout << "Introduceti un
character: ";
cin >> Ch;
k = 0;
for (rhs.begin(); k <
rhs.length(); rhs.end())
{
if (k == x)

k = 0;
for (rhs.begin(); k <
rhs.length(); rhs.end())
cout << "[" << rhs[k++] <<
"]";
system("pause");
return rhs;
}
// Compararea sirurilor
bool operator== (const char * Str)
const;
bool operator== (const String& Str)
const;
bool operator!= (const char * Str)
const;
bool operator!= (const String& Str)
const;
bool operator < (const char * Str);
bool operator < (String& Str);
bool operator > (const char * Str);
bool operator > (String& Str);
int Compare(const char *Str) const;
int Compare(String& Str) const;
void Set(const char *Str);
void Set(const String& Str);
char* Get() const;
// Aflarea lungimei sirurlui
int StrLength() const;
friend ostream& operator<< (ostream&
Out, String& Str);
friend istream& operator>> (istream&
In, String& Str);
};
String::String()
{
_Size = 0;
_String = 0;
}
String::~String()
{
delete[] _String;
_String = NULL;
}
String::String(const char *Str)

_Size++;
char *Temp = new char[_Size + 1];
strcpy(Temp, _String);
delete[] _String;
_String = Temp;
Temp += _Size;
*Temp = '\0';
Temp--;
*Temp = Ch;
return *this;

_String = new char[strlen(Str) + 1];


strcpy(_String, Str);
}
String::String(const String& Str)
{
_String = new char[strlen(Str._String)
+ 1];
strcpy(_String, Str._String);
}
// supraincarcarea operatorului +
String operator+(const String& S1, const
String& S2)
{
char *Temp = new char[S1.StrLength() +
S2.StrLength() + 1];
strcpy(Temp, S1.Get());
strcat(Temp, S2.Get());
return String(Temp);
}
// copierea sirului *char
String& String::Copy(const char *Str)
{
delete[] _String;
_Size = strlen(Str);
_String = new char[_Size + 1];
strcpy(_String, Str);
return *this;
}
// copierea sirului tip string
String& String::Copy(String& Str)
{
Copy(Str._String);
return *this;
}
// \concatinarea sirului *char
String& String::Cat(const char *Str)
{
_Size = Length() + strlen(Str);
char *Temp = new char[_Size + 1];
strcpy(Temp, _String);
strcat(Temp, Str);
delete[] _String;
_String = Temp;
return *this;
}
// concatinarea sirului de tipul clasei
String& String::Cat(String& Str)
{
Cat(Str._String);
return *this;
}
// Concatinarea simbolului
String& String::Cat(char Ch)
{

}
// supraincarcarea operatorului += cu
argumentul de tip *char
String& String::operator+= (const char *Str)
{
Cat(Str);
return *this;
}
// supraincarcarea operatorului += cu
argumentul de tipul clasei
String& String::operator+= (String& Str)
{
Cat(Str);
return *this;
}
// supraincarcarea opertorului += cu
argumentul pentru simbol
String& String::operator+= (char Ch)
{
Cat(Ch);
return *this;
}
// Supraincarcarea operatorului =
String& String::operator=(const String& Str)
{
char *Temp = new
char[strlen(Str._String) + 1];
strcpy(Temp, Str._String);
delete[] _String;
_String = Temp;
return *this;
}
// supraincarcarea operatorului == cu
argumentul de tip *char
bool String::operator== (const char *Str)
const
{
if (Compare(Str) == 0)
return true;
return false;
}
// operator==

bool String::operator== (const String& Str)
const
{

if (Compare(Str._String) == 0)
return true;
return false;
}
// supraincarcarea operatorului != cu
argumentul de tip *char
bool String::operator!= (const char * Str)
const
{
if (Compare(Str) != 0)
return true;
return false;
}
// supraincarcarea operatorului != cu
argumentul de tip clasa
bool String::operator!= (const String& Str)
const
{
if (Compare(Str._String) != 0)
return true;
return false;
}
// supraincarcarea operatorului < cu
argumentul de tip *char
bool String::operator < (const char *Str)
{
if (Compare(Str) < 0)
return true;
return false;
}
// supraincarcarea operatorului < cu
argumentul de tip clasa
bool String::operator < (String& Str)
{
if (Compare(Str._String) < 0)
return true;
return false;
}
// supraincarcarea operatorului > cu
argumentul de tip *char
bool String::operator > (const char * Str)
{
if (Compare(Str) > 0)
return true;
return false;
}
// supraincarcarea operatorului > cu
argumentul de tip clasa
bool String::operator > (String& Str)
{
if (Compare(Str._String) > 0)
return true;
return false;
}
// Compararea sirurilor, argumentul de tip

*char trimis de obiect se compara cu membru


_String
int String::Compare(const char *Str) const
{
return (strcmp(_String, Str));
}
// Compararea sirurilor, argumentul de tip
clasa trimis de obiect se compara cu membru
_String
int String::Compare(String& Str) const
{
return (strcmp(_String, Str._String));
}
// Aflam lungimea sirului trimis ca argument
si trimitem ca argument in functia Set
void String::Set(const char *Str)
{
Set(String(Str));
}
// Adaugam un sir
void String::Set(const String& Str)
{
*this = Str;
}
// returnam sirul _String
char* String::Get() const
{
return _String;
}
// Aflam lungimea sirului _String
int String::StrLength() const
{
return strlen(_String);
}
istream& operator>> (istream& Input, String&
Str)
{
Input >> Str._String; return Input;
}
ostream& operator<< (ostream& Output, String&
Str)
{
Output << Str._String; return Output;
}

int
{

main()

int op;
String IsSpace = " ", ObjectA, ObjectB,
ObjectC;
char FirstStr[128], SecondStr[128];
String ObjectArray;

while (1)
{
system("cls");
cout << "
Meniu\n\n";
cout << "[1]: Introducerea
sirurilor de caractere\n";
cout << "[2]: Operator \"+ \" |
Concatinarea sirurilor de caractere\n";
cout << "[3]: Operator \"= \" |
Atribuire\n";
cout << "[4]: Operator \"+=\" |
Concatinare cu atribuire\n";
cout << "[5]: Operator \"==\" |
Compararea sirurilor pentru egalitate\n";
cout << "[6]: Operator \"!=\" |
Compararea sirurilor pentru inegalitate\n";
cout << "[7]: Operator \"< \" |
Compararea sirului care este mai mic decit
\n";
cout << "[8]: Operator \"> \" |
Compararea sirului care este mai mare
decit\n";
cout << "[9]: Operator \"[]\" |
Acces la fiecare simbol\n";
cout << "[0]: Iesire\n\n";
cout << "Introduceti optiunea:"
<< endl;
cin >> op;
switch (op)
{
case 1:
system("cls");
cout << "Introduceti
primul sir: ";
cin >> FirstStr;
cout << "Introduceti
aldoilea sir: ";
cin >> SecondStr;
ObjectA = FirstStr;
ObjectB = SecondStr;
system("cls");
cout << "Sirurile sunt :"
<< endl;
cout << " << " << ObjectA
<< " >> \n";
cout << " << " << ObjectB
<< " >> \n";
break;
case 2:
system("cls");
cout << "Sirurile sunt :"
<< endl;
cout << " << " << ObjectA
<< " >> \n";
cout << " << " << ObjectB
<< " >> \n";
cout << "Sirul concatinat:
";
ObjectC = ObjectA +
IsSpace + ObjectB;

ObjectC.Get();
cout << " << " << ObjectC
<< " >> \n";
break;
case 3:
system("cls");
ObjectC = "Acesta este un
exemplu de sir atribuit...\n";
ObjectC.Get();
cout << ObjectC;
break;
case 4:
system("cls");
ObjectA += ObjectB;
ObjectA.Get();
cout << "\nAtribuirea
sirurilor combinate: ";
cout << ObjectA << endl;
break;
case 5:
system("cls");
if (ObjectA == ObjectB)
cout << "Sirurile
sunt egale!" << endl;
else
{
cout << "Sirurile
nu sunt egale!" << endl;
}
break;
case 6:
system("cls");
if (ObjectA != ObjectB)
{
cout << "Sirurile
nu sunt egale!" << endl;
}
else
cout << "Sirurile
sunt egale" << endl;
break;
case 7:
system("cls");
cout << " << " << ObjectA
<< " >>
";
cout << " << " << ObjectB
<< " >>
\n";
if (ObjectA < ObjectB)
cout << "Sirul << "
<< ObjectA << " >> este mai mic!" << endl;
else
cout << "Sirul << "
<< ObjectB << " >> este mai mic!" << endl;;
break;
case 8:
system("cls");
cout << " << " << ObjectA
<< " >>
";
cout << " << " << ObjectB
<< " >>
\n";
if (ObjectA > ObjectB)

cout << "Sirul << "


<< ObjectA << " >> este mai mare!" << endl;
else
cout << "Sirul << "
<< ObjectB << " >> este mai mare!" << endl;
break;
case 9:
system("CLS");
ObjectArray["C++. The best
programming language!"];
break;

return 0;
default:
system("cls");
cout << "Ati introdus o
optiune gresita!" << endl;
break;
}
system("pause");
}

case 0:

Screen-urile programului:
Fig 1: Sarcina a

Fig 2: Sarcina b

Concluzie
n urma elaborrii lucrrii de laborator am am captat cunotinele de baz in programarea pe obiecte si
anume cu clasele i ne-am familiarizat cu supraincarcarea operatorilor cat si aplicaia constructorilor i
destructorilor n limbajul C++. De asemenea am studiat i am realizat n practic supraincarcarea
operatorilor i am concluzionat aplicabilitatea acestora n diferite situaii. Am observat ca :
Iata lista operatorilor din C++ care se pot supraincarca: new delete () [] + - * / % ^ & | ~ ! = < > += -= *=
/= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* ->
Operatorul () este apelul unei functii, iar operatorul [] este operatorul de indexare.
Urmatorii operatori nu se pot supraincarca: . .* :: ?: sizeof.
Reguli care trebuie sa fie respectate in supraincarcarea operatorilor:

Operatorii =, (), [], si -> trebuie sa fie membrii nestatici ai clasei


o Operatorul = nu poate fi mostenit
o Operatorii pentru tipurile predefinite ale limbajului nu se pot supraincarca
o Operatorii nu pot avea argumente impliciteaceasta este o metoda buna pentru a crea
clase de nivel inalt,la fel am supraincarcat citeva operatoare pentru a lucra cu
obiectele create de clase.

Bibliografie:

Nabajyoti Barkakati Borland C++ Ghidul programatorului

Catrina Octavian, Cojocaru Iuliana Turbo C++

Dr. Kris Jamsa & Lars Klander Totul despre C si C++ Ghid