An1 Sem2 Curs7 Eng Over
An1 Sem2 Curs7 Eng Over
Algorithms
Semester 2
Module 2
English classes
Course 7
1
Overloading functions and methods
Methods (member functions) belong to
classes, functions (simple) are outside classes
• Overloading based on the signature:
– Same name
– Different : number, type and order of parameters, the
return value is ignored
– Usual different implementations for functions:
int myFunction(int x){
return x;
}
4
Methods overloading
• Inside classes, methods (member functions) can be
overloaded. Usual constructors are overloaded.
• We have no overloading when:
-Two functions with the same name, one
independent (global) and one member of a class
-Two methods with the same name, each member of
another class, no correspondence between them
5
Overloading operators
• Overloading operators involves assigning new meanings
to operators to expand their scope to other types of data,
including objects from classes.
• Consider that we have a Complex class with methods
that perform the basic operations, and we want to
perform operations with complex numbers:
Complex a, b, c, d, e;
e = mulcomplex(adcomplex(&a, &b), sccomplex(&c, &d));
8
Characteristics:
- By overloading, new operators can not be introduced
- Predefined types are not allowed to be overloaded
- The operator overloading can not change:
• n-arity
• priority
• associativity
- Compound operators (+=, -=, …) are not affected by
overloading of base operators (+, -, =, …):
• For these operators, an explicit overloading must
be provided in each case
- If an operator may be used as unary and binary operator
(&, *, +, -) different overloading's must be provided for both
cases 9
• Operators: ->, =, [ ] and ( ) and compound operators can be
overloaded only with methods (member functions).
• Extraction >> and<< insertion operators are always overloaded
with friend functions, or global independent functions.
• Usually the following rules are respected:
- unary operators are overloaded with methods
- the binary operators that do not modify an operand are
overloaded with friend functions
- the binary operators that modifies an operand are
overloaded with methods
class Complex {
double re, im;
public:
Complex( ) {
re = 0.;
im = 0.;}
Complex(double x, double y) {
re = x;
im = y; }
double getRe( ) {
return re; }
double getIm( ) {
return im; }
//overloading with member methods
//Complex operator+(Complex x);
Complex operator-(Complex x);
//Complex * operator-(Complex *x);
Complex & operator+(const Complex &);
};//Complex class 12
/*Complex Complex :: operator+(Complex x) {
Complex rez;
rez.im = im + x.im;
rez.re = re + x.re;
return rez; }*/
int main( ) {
Complex unu(5., 3.), doi(-1., 6.), trei;
cout << "\nFirst number: "<<unu.getRe( ) <<" +i* " <<unu.getIm( )<<endl;
cout << "\nSecond number " << doi.getRe( ) << " +i* " << doi.getIm( ) << endl;
/*cout<< "\n Sum (doi + unu) ";//Sum, transfer by value
trei = doi + unu;
cout << "\nSum result by value: " << trei.getRe( ) << " +i* " << trei.getIm( ) << endl; */
// Sum, equivalent with explicit call: Complex &ref_trei= doi.operator+(unu)
cout << "\n Sum: (doi + unu) ";
Complex &ref_trei = doi + unu;
cout<<"\nSum result by reference: " << ref_trei.getRe( )<<" +i*"<<ref_trei.getIm( )<<endl;
//Difference, equivalent with explicit call: trei=doi.operator-(unu)
cout << "\n Difference: (doi - unu) ";
trei = doi - unu;
cout << "\nDifference result: " << trei.getRe( ) << " +i* " << trei.getIm( ) << endl;
//Complex *patru = doi - &unu; //(doi.operator-(&unu))
//cout<<"\nDifference result by pointer: "<< patru->getRe( )<<" +i*" << patru->getIm()<<endl;
}//main
14
Overloading operators with
friend functions
• This case requires explicit transfer of all required
operands because friend functions are not member in
the class and therefore have no access to this pointer:
- Unary operators have a parameter
- Binary operators have two parameters
• General form:
int main( ) {
Complex unu(5., 3.), doi(-1., 6.);
Complex trei;
cout << "\nFirst number: " << unu.getRe( ) << " +i* " << unu.getIm( ) <<
endl;
cout << "\nSecond number " << doi.getRe( ) << " +i* " << doi.getIm( ) <<
endl;
Complex &r_trei = doi + unu;
//equivalent with explicit call: Complex &r_trei = operator+(doi, unu)
cout << "\nSum (doi + unu): " << r_trei.getRe( ) << " +i* " <<
r_trei.getIm( ) << endl;
trei = doi - unu;
//equivalent with explicit call: trei = operator-(doi, unu)
cout << "\nDifference: (doi - unu) " << trei.getRe( ) << " +i* " <<
trei.getIm( ) << endl;
}//main
18
• The overloading choosing method is not imposed and
should be given by: n-arity operator, protection
considerations and operands modifying value;
- Unary operators are usually implemented with member
functions (methods)
- Binary operators, that are used to modify the value of an
operand, are overloaded with member functions (methods)
- friend functions allow a first operand as primitive type, so,
not an object. In this sense they are more flexible than the
member functions (methods) that have always as the first
operand the current object
- Operators that will not modify operands but will generate
new values can be overloaded with global functions:
• a global function can be of a friend type, in which case will
access all data of the class, or may be an independent
function that accesses the data by means of interface
methods (getter public methods)
19
Member function - Global function
Expression Operator
method - friend
@A + - * & ! ~ ++ -- A::operator@() operator@(A)
A@ ++ -- A::operator@(int) operator@(A,int)
+ - * / % ^ & | <
A@B > == != <= >= << A::operator@ (B) operator@(A,B)
>> && || ,
= += -= *= /= %=
A@B ^= &= |= <<= >>= A::operator@ (B) -
[]
A(B,C...) () A::operator( ) (B, C...) -
A->x -> A::operator->( ) -
27
class Rectangle {
private:
Point topLeft;
Point botRight;
public:
Rectangle(int left, int top, int right, int bottom);
Rectangle(const Point &p, const Point &q) : topLeft(p), botRight(q) { }
Rectangle(const Point &p) : topLeft(p), botRight(p) { }
void print(void) {
topLeft.print( ); //method from Point class
botRight.print( );
}
};//Rectangle class
28
Rectangle::Rectangle(int left, int top, int right, int bottom): topLeft(left, top), botRight(right,
bottom){ } //explicit constructor with parameters
//friend functions
Rectangle operator+(Rectangle &r, Rectangle &t) {
return Rectangle(r.topLeft + t.topLeft, r.botRight + t.botRight);}
Rectangle operator-(Rectangle &r, Rectangle &t) {
return Rectangle(r.topLeft - t.topLeft, r.botRight - t.botRight);}
//main
#include <iostream>
using namespace std;
#include "Point_rectangle.h"
int main( ) {
Point p(10, 10), q(20, 20);
cout << "\nPoint p is:";
p.print( );
cout << "\nPoint q is:";
q.print( );
cout << "\nPoint p + q is:";
(p + q).print( );
cout << '\n';
cout << "\nPoint p + 10 is:";
(p + 10).print( ); //equivalent with operator+(p, Point(10))
Rectangle r(10, 10, 20, 30);
cout << "\nRectangle r is:";
r.print( );
Rectangle s = r + p; //equivalent with operator+((Point)r,p)
cout << "\n Sum of Rectangle r with Point p\n";
s.print( );
cout << "\n Difference of Rectangle r with Point p\n";
Rectangle t = r - p;
t.print( ); 29
}//main
• As a synthesis, using objects can lead to situations where
are necessary conversions.
• These conversions can not be applied automatically as
for predefined types.
• The user can define these types of conversion:
a)from predefined type -> in abstract type
b)from abstract type -> in predefined type
c)from abstract type -> in abstract type
30
• b)Conversion from abstract type -> in predefined type it
is realized by overloading cast operator with a member
function (method):
Class_name:: operator predefined_type_Name ( ) {
// body method
}
The method has no parameter, because the cast
operator is unary.
• It is called for an object of type Class_name and return
a value of type predefined_type_Name.
• It is used as for predefined types :
(predefined_type_Name) object
or,
predefined_type_Name (object) 31
• c)Conversion from abstract type -> in abstract type
This conversion can be realized with conversion
constructors or by overloading the cast operator (Rectangle
to Point).
• If we have type1 and type2 two abstract types, to convert
an object of type1 in object of type2, we define a
constructor for class type2 that will have as parameter
an object of type1as: type2(type1 object);
• This constructor must have access to data of class type1
that are usually protected.
32
Overloading the assign operator
• For assignments between objects of the same type (no
pointers as attributes), it is used a variant of the default
overloaded assignment operator.
• This variant provides data copying byte by byte using a
serialization process.
• If the constructors made d ynamic allocation, and classes
contain pointers attributes to be defined dynamically at
runtime, the default option is not satisfactory, and it is
necessary to provide an explicit overload variant. In this
case usual it is also necessary to overload the copy
constructor (and move constructor if necessary).
• The general form of the method to overload the
assignment operator is: 33
Type& Type ::operator=(const Type &source) {
if(this != & source) {//verify autocopy
// free space dynamically allocated for attributes of the current
object if current and source objects are different as dimension !!!
//this->~Type( );//you may use if Type is the class, and we have
destructor
//alloc dynamically space for attributes given by pointers of the
current object considering the right member object dimensions
//data copy of the right member object to the current object
}
return *this;
}
35
Examples: Array, Matrix and String
//Array.h
const int dim = 10;
class Array {
double* arr;
int length;
public:
Array(int number = dim) {
length = number;
arr = new (nothrow) double[length];
}
int main( ) {
Array ob1, ob2;
// cout << "Introduce the number of elements of the first array and second array (< "<< dim <<"):";
int n, m;
do {
cout<<"\nEnter the dimension of the first array (< " << dim << "):";
cin>>n;
if (n > dim) cout<<"\nThe dimension is too big! Choose again\n";
if (n <= 0) cout<<"\nThe dimension is not valid!\n";
} while (n > dim || n <= 0);
ob1.setLength(n);
double* p = new (nothrow) double[n];
srand((unsigned)time(NULL));
for (int i = 0; i < n; i++)
{
//p[i] = static_cast <double> (rand()) / (static_cast<double> (RAND_MAX / (100)));//with generics
p[i] = ((double)rand()) / ((RAND_MAX / (100)));
}
ob1.setArr(p);
delete[ ] p;
38
do {
cout << "\nEnter the dimension of the second array (< " << dim << "):";
cin >> m;
if (m > dim) cout << "\nThe dimension is too big! Choose again\n";
if (m <= 0) cout << "\nThe dimension is not valid!\n";
} while (m > dim || m <= 0);
ob2.setLength(m);
p = new (nothrow) double[m];
for (int i = 0; i < m; i++)
p[i] = ((double)rand()) / ((RAND_MAX / (100)));
ob2.setArr(p);
delete[ ] p;
cout << endl << "The first array of doubles is:" << endl;
ob1.displayArray();
cout << endl << "And the second one:" << endl;
ob2.displayArray();
cout << endl << "The resulting difference array is:";
int l;
if (ob1.getLength() < ob2.getLength()) l = ob1.getLength();
else l = ob2.getLength();
Array ob3;
// Array ob3 = ob1.difArray(ob2, l);//copy cons.
ob3 = ob1.difArray(ob2, l);//assign
cout << endl;
ob3.displayArray();
cout << "\nCopy/Move constructor difference is:\n";
Array ob4 = ob1.difArrayM(ob2);//copy and move constructor
ob4.displayArray();
cout << endl << "The clone of resulting array is:\n";
Array ob5 = ob3;//copy cons.
ob5.displayArray();
// cout << "\nEnter a character";
cin.get(); 39
}//main
// Matrix – complete example at the end of document
class Matrix {
int rows, cols;
int *elems;
public:
Matrix (int rows, int cols);
~Matrix ( ) {
delete [ ] elems; }
Matrix (const Matrix&);//copy constructor
Matrix& operator = (const Matrix &m);
//overloading assign operator
40
};//Matrix class
Matrix::Matrix (const int r, const int c) : rows(r), cols(c)
{ // to verify before if (r > r && c > 0)
elems = new (nothrow) int[rows * cols];
}
Matrix::Matrix (const Matrix &m) {//copy constructor
int n;
rows = m.rows;
cols = m.cols;
//to verify before if (m.rows > 0 && m.cols > 0), if m exist
n = rows * cols;
elems = new (nothrow) int[n];
for (int i = 0; i < n; ++i)
elems[i] = m.elems[i];
}
41
Matrix& Matrix::operator = (const Matrix &m) //assign
{
if (this != &m)
{
//if (rows == m.rows && cols == m.cols) //to verify before in main
//{
delete [ ] elems;//this->~Matrix();
rows = m.rows;
cols = m.cols;
n = rows * cols;
elems = new (nothrow) int[n];
for (int i = 0; i < n; ++i)
elems[i] = m.elems[i];
//}
//else cout<<"\nWrong dimensions\n";
}
else cout<<"\nAuto-assign!\n";
return *this;
} 42
//String class
class String {
char *p;
int size;
public:
String(char *str);
String( );//will alloc space for p
String(const String &obj); //copy constructor
~String( ) {
delete [ ] p;
}
43
// overloading operator + (concatenate)
// String operator+(String &obj); //with member method and param. by address
/*
String operator+ (String x1) { //overloading with member method
String rez;
rez.~String();//delete [ ]p;
rez.sir = new (nothrow) char[strlen(this->sir)+strlen(x1.sir) + 1];
strcpy(rez.sir, sir);
strcat(rez.sir, x1.sir);
return rez;
}
*/
friend String operator+(String &obj1, String &obj2);
String operator+(char *s);
friend String operator+(char *s, String &obj);
44
// overloading relational operators (compare current object with
another object)
46
int strsize(void)
{ return strlen(p); }
char* makestr(char *s)
{ return strcpy(p, s); }
operator char *(void)
{ return p; }
}; // clasa String
47
String operator+(String &a,String &b){
char *buf= new (nothrow) char[strlen(a.sir)+strlen(b.sir) + 1];
strcpy(buf,a.p);
strcat(buf,b.p);
return String(buf);
}
String operator-(String &a, String &b){
char *pp;
pp = strstr(a.p, b.p); // adresa unde începe sirul b.p in sirul a.p
if(pp == NULL) // sirul nu se gaseste in a.p
return String(a.p);
else {
char* buf = new (nothrow) char[strlen(a.sir) + 1];
strncpy(buf, a.p, pp-a.p);
strcpy(buf+(pp-a.p),pp+strlen(b.p));
return String(buf);
}
}
…
Remark: A complete example lab 9
48
//CPuncText- copy constructor and assign overloading
const int dim_sir = 21;//20 +1 for \0
class CPunctText {
int x;
int y;
char* sNume;
public:
CPunctText( ) {
//cout << "\n empty explicit constructor";
x = y = 0;
sNume = new (nothrow) char[dim_sir];
}
CPunctText(int ix, int iy, const char* sText = "Punct") {
//cout << "\n constructor with parameters";
sNume = new (nothrow) char[strlen(sText) + 1];
x = ix;
y = iy;
cout << "\nLength string:\n" << strlen(sText);
//strcpy_s(sNume, strlen(sText) + 1, sText);
strcpy(sNume, sText);
}
CPunctText(const CPunctText& pct) {
cout << "\n copy constructor";
sNume = new (nothrow) char[strlen(pct.sNume) + 1];
x = pct.x;
y = pct.y;
//strcpy_s(sNume, strlen(pct.sNume) + 1, pct.sNume);
strcpy(sNume, pct.sNume);
}
49
CPunctText& operator= (const CPunctText& pct) {
cout << "\n overload assign";
if (this == &pct) return *this;
delete[ ] sNume;//delete string of current object as: this-> ~CPunctText();
sNume = new (nothrow) char[strlen(pct.sNume) + 1];//alloc string with the assign
object
x = pct.x;
y = pct.y;
//strcpy_s(sNume, strlen(pct.sNume) + 1, pct.sNume);
strcpy(sNume, pct.sNume);
return *this;
}
~CPunctText() {
cout << "\nDestructor is called" << endl;
delete[ ] sNume;
}
int getX() {
return x;
}
int getY() {
return y;
}
char* getSNume() {
return sNume;
}
CPunctText sum(CPunctText);
double distance( );
};//CPunctText
double CPunctText::distance() {
return sqrt(x * x + y * y);
} 50
CPunctText CPunctText::sum(CPunctText pct) {
CPunctText c;
c.~CPunctText();//free spece for char* attribute
c.sNume = new (nothrow) char[strlen(this->sNume) + strlen(pct.sNume) + 1];
c.x = x + pct.x;
c.y = y + pct.y;
//strcpy_s(c.sNume, strlen(this->sNume) + 1, sNume);
//strcat_s(c.sNume, strlen(this->sNume) + strlen(pct.sNume) + 1, pct.sNume);
strcpy(c.sNume, sNume);
strcat(c.sNume, pct.sNume);
return c;
}
//main
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include "CPunctText.h"
int main( ) {
CPunctText cpt1(1, 2, "Punct1");//constructor with parameters
CPunctText cpt2(cpt1); //copy constructor
CPunctText cpt3 = cpt2; //copy constructor
CPunctText cpt4(4, 5); //constructor with parameters
CPunctText cpt5(3, 4, "Punct5"); //constructor with parameters
cout << "\nThe distance from the origin to " << cpt5.getSNume() << " is " << cpt5.distance();
CPunctText cpt = cpt1.sum(cpt5);//copy constructor
cout << endl << "The sum is: " << cpt.getSNume() << " " << cpt.getX() << " " << cpt.getY();
CPunctText acpt;
acpt = cpt1.sum(cpt5);//need assign, =, overloading
cout << endl << "The sum with assign is: " << acpt.getSNume() << " " << acpt.getX() << " " <<
acpt.getY();
}//main
51
Overloading new and delete
operators
• Purpose: to perform some special operations allocation/
release memory when creating or destroying an object of
a class
• A) We have for ADT a standard - global overloading.
• B) The operators new and delete can be overloaded only
with static member methods (not explicitly specified)
• The general syntax of local overload (or user) of these
operators with static methods (not explicitly specified) is:
void *operator new(unsigned dim){
… // memory alloc operations
return pointer_to_new_memory_zone}
void operator delete(void *p, [unsigned dim]){
… // free zone pointed by p} 52
• When applying this operator, we do not indicate any value
for the formal parameter dim, the compiler will
automatically calculate the size of the object for which to
reserve the memory area, dimension which will be
assigned to parameter dim
• The calling process is realized by:
new Class_name ;
or:
new Class_name(par1, par2, …, parn) ;
• new and delete operators have a particular characteristic:
- Have a global overload (standard or predefined) offered
by the language for abstract types (ADT)
- Can have a local overload to a class realized by the user
- Simultaneous global overloading can be used by a
construction like: :: new Class_name;
53
• The global overloading allows objects arrays allocation,
and the local overloading, by default, not
• So, modern C++ code should accept calling new, new[ ],
delete, and delete[ ] directly, as global overloading.
• The elements initialization is not allowed at the global
overloading with an explicit constructor with parameters,
and so it is used another mechanism (an init method, ...)
• If we want to alloc/release memory for arrays with the
local overloading, the following syntax it is used:
void *operator new[ ](unsigned dim){
… // memory alloc operations
return pointer_to_new_memory_zone
}
void operator delete[ ](void *p, [unsigned dim]){
… // free zone pointed by p
54
}
Example 1: new and delete operators:
//Pozitie.h header
class Pozitie {
int x;
int y;
public:
Pozitie( ) {x=y=0; }
Pozitie(int oriz, int vert) {
x = oriz;
y = vert;
}
int getX( ) {
return x; }
int getY( ) {
return y; }
int main( ) {
Pozitie *p1, *p2;
p1 = new Pozitie(100, 200);//local overloaded
if (!p1) {
cout<<"\n No memory for P1.";
exit(0);
}
p2 = new Pozitie(10, 20);//local overloaded
if (!p2) {
cout<<"\n No memory for P2.";
exit(1);
}
cout << "\nPosition in plan P1 with coordinates: " << p1->getX( ) << " " << p1->getY( );
cout << "\nPosition in plan P2 with coordinates: " << p2->getX( ) << " " << p2->getY( );
delete(p1); //overloaded
delete(p2); //overloaded
}//main 56
Example2: new and delete
// Point.h header
const int maxPoints = 2;
class Point {
int xVal, yVal;
public:
Point(int x, int y) { xVal = x; yVal = y; }
void* operator new (size_t bytes);
void operator delete (void* ptr, size_t bytes);
int main( ) {
Point* pt1 = new Point(1, 1);//call Point::operator new local static
if (pt1 != 0) pt1->show1();
else cout << "\nNo space memory..." << endl;
Point::show2();
Point* pt2 = new Point(2, 2);//call Point::operator new local static
if (pt2 != 0) pt2->show1();
else cout << "\nNo space memory..." << endl;
Point::show2();
pt2 = new Point(3, 3);//call Point::operator new local static
if (pt2 != 0) pt2->show1();
else cout << "\nNo space memory..." << endl; 58
Point::show2();
cout << "Deleting object...." << endl;
delete pt1; //call Point::operator delete local static
Point::show2();
pt2 = new Point(4, 4);//call Point::operator new local static
if (pt2 != 0) pt2->show1();
else cout << "\nNo space memory..." << endl;
Point::show2();
pt2 = new Point(5, 5);//call Point::operator new local static
if (pt2 != 0) pt2->show1();
else cout << "\nNo space memory..." << endl;
Point::show2();
char* str = new (nothrow) char[10];//call ::operator new global
delete [ ] str; //call ::operator delete global
}//main
59
Overloading the indexing
operator, [ ]
Overloading this operator is made for those data types that
have a similar behavior with arrays
• An example is the associative array, the indexes can be of
any ordered type
• By overloading this operator, a behavior like this will be
obtained:
a[b] a.operator[ ](b)
If indexing operator is overloaded for a certain type, the
arrays of this type can not be initialized by a construction of
the form:
Type array_name[ ] = {val1, val2,…, valn};
We initialize only using constructors with parameters. 60
Example BitVec and Dictionar:
// BitVec.h header
typedef unsigned char uchar;
class BitVec {
uchar *vec;
short bytes;
public:
BitVec (const short dim);
BitVec (const char* bits);
BitVec (const BitVec&);//copy_constructor
~BitVec ( ){ delete vec; }
BitVec& operator = (const BitVec&);//assign
int operator [ ] (const short idx);
void print ( );
};//BitVec class
61
BitVec::BitVec (const char *bits){
int len = strlen(bits);
bytes = len / 8 + (len % 8 == 0 ? 0 : 1);
vec = new (nothrow) uchar[bytes];
for (int i = 0; i < bytes; ++i) vec[i] = 0;
int main ( ){
BitVec v("1011011101111");
v.print( );
cout << endl << "\nBits are: " << dec << endl;
for(int i=0; i< 16; i++)
cout << "Bit " << (i+1) << ": " << v[i] << endl;
BitVec vv(16);
cout<<"\n New vector is:";
vv.print( );
vv=v;
cout<<"\n New vector after assign is :";
vv.print( );
cout << endl << "\nBits are: " << dec << endl;
for(int i=0; i< 16; i++)
cout << "Bit " << (i+1) << ": " << v[i] << endl;
}//main 64
// Dictionar.h
struct Assoc {
char *cuvant;
char *definitie;
};
class Dictionar {
Assoc *dict;
int dim;// dictionary dim
int next;// next free position in dictionary
public:
Dictionar(int size) {
dim = size;
next = -1;
dict = new (nothrow) Assoc[size];
}
int addWord(const char *w, const char *def);
char *operator[ ](const char *);
};//Dictionar_class 65
int Dictionar::addWord(char *p, char *def){
if(next < dim) {
next++;
errno_t er;
dict[next].cuvant = new (nothrow) char[strlen(p)+1];
//er=strcpy_s(dict[next].cuvant, strlen(p)+1, p);
er=strcpy(dict[next].cuvant, p);
dict[next].definitie = new (nothrow) char[strlen(def)+1];
//er=strcpy_s(dict[next].definitie,strlen(def)+1, def);
er=strcpy(dict[next].definitie, def);
return 0;
}
return 1;
}//addWord
int main( ){
int size = 10;
Dictionar dict(size);
dict.addWord("Masina", "Definitia 1");
dict.addWord("Copac", "Definitia 2");
dict.addWord("Animal", "Definitia 3");
dict.addWord("Student", "Definitia 4");
cout << dict["Animal"]<<endl;
}//main 67
Example: Analize class
//PersAnalize.h header
const int dim_chr = 20;
class Analize;
class Pers
{
char nume[dim_chr];
double greutate;
int varsta;
friend Analize;
public:
void tip( );
};// Pers
void Pers::tip( )
{
if (this)cout << "\nPerson : " << nume << "\tWeight : " << greutate <<
"\tAge : "<<varsta;
else cout << "\nNo object ";
68
}
const int dim = 5;
class Analize {
Pers *sir;
int n;
public:
Analize( )
{
n=dim;
sir= new (nothrow) Pers[dim];
}
Analize(int nr)
{
n=nr;
sir= new (nothrow) Pers[n];
}
//Overloading [ ]
Pers* operator[ ](char *);
Pers* operator[ ](double);
Pers* operator[ ](int);
void introdu( ); // method to read data – must be defined
};//Analize 69
//Indexing by name
Pers* Analize:: operator[ ](char *nume)
{
for(int i=0;i<n;i++)
if(strcmp(sir[i].nume,nume)==0)return &sir[i];
return NULL;
}//op[ ]nume
//Indexing by weight
Pers* Analize:: operator[ ](double gr)
{
for(int i=0;i<n;i++)
if(sir[i].greutate==gr)return &sir[i];
return NULL;
}//op[ ]greutate
//Indexing by index
Pers* Analize:: operator[ ](int index)
//recomended to validate outside the index
{
if((index >=1) && (index <=n))return &sir[index-1];
else {cout << "\nWrong Index";return NULL;}
}//op[ ]index
70
//main
#include <iostream>
using namespace std;
#include "PersAnalize.h"
int main( ){
int nr=dim;
double g;
char *n;
int i;
// g, n and i , complete example in …. Examples_curs6-7_2024
75
int& Matrix::operator( ) (const short row, const short col)
{
//if (row >= 0 && row < rows)
// if (col >= 0 && col < cols) //to verify all outside
return elems[row*cols + col];
}
Matrix n=m;
cout<<endl;
for(i=0; i<2; i++) { cout<<endl;
for(j=0; j<3; j++)
cout<<n(i, j)<<"\t";
} 77
}//main
Complete matrix example, linear storage
//Matrix.h header
class Matrix {
int rows;
int cols;
int *elems;
public:
Matrix( );
Matrix(int rows, int cols);
Matrix(const Matrix&);
~Matrix( ) { delete [ ] elems; }
int& operator ( ) (int row, int col);
Matrix& operator=(const Matrix&);
//friend Matrix operator+(Matrix&, Matrix&);
Matrix operator+(Matrix&);//method
friend Matrix operator-(Matrix&, Matrix&);
friend Matrix operator*(Matrix&, Matrix&);
int getRows( ) { return rows; }
int getCols( ) { return cols; }
void init(int r, int c);
void citire( );
void afisare( );
};//Matrix 78
Matrix::Matrix( ) : rows(linii), cols(coloane)
{
elems = new (nothrow) int[rows * cols];
}
Matrix::Matrix(int r, int c) : rows(r), cols(c)
{
elems = new (nothrow) int[rows * cols];
}
Matrix::Matrix(const Matrix &m) : rows(m.rows), cols(m.cols)
{
int n = rows * cols;
elems = new (nothrow) int[n];
for (int i = 0; i < n; i++)
elems[i] = m.elems[i];
}
79
Matrix& Matrix:: operator=(const Matrix &m) {
if (this != &m){
delete [ ] elems;
rows=m.rows; cols=m.cols;
int n = rows * cols;
elems = new (nothrow) int[n];
for (int i = 0; i < n; i++)
elems[i] = m.elems[i];
}
return *this;
}//op=
/*
Matrix operator+(Matrix &p, Matrix &q) {
Matrix m(p.rows, p.cols);
for (int r = 0; r < p.rows; ++r)
for (int c = 0; c < p.cols; ++c)
m(r, c) = p(r, c) + q(r, c);
return m;
}//op+ friend*/
81
//main
#include<iostream>
using namespace std;
#include "Matrix.h"
int main( ) {
int i, j;
Matrix m(linii, coloane);
cout << endl << "\nE nevoie ca operator( ) sa fie supraincarcat pentru a lucra element cu element din matrice: \n";
int l, c;
cout << "Verificarea supraincarcarii operatorului ( ) pentru un element de pe o pozitie citita de la tastatura" << endl;
cout << "Dati numarului liniei (>=1): ";
cin >> l;
cout << "Dati numarului coloanei (>=1): ";
cin >> c;
82
if ((l >= 1 && l <= m.getRows( )) && (c >= 1 && c <= m.getCols( )))
cout << "Elementul m[" << l << "," << c << "]=" << m(l - 1, c - 1) << endl;
else
cout << "Indici eronati!" << endl;
cout << endl << "Utilizare constructor de copiere:" << endl;
if (m.getRows( )> 0 && m.getCols( )> 0){
Matrix mcopy = m;
cout << "Matricea \"mcopy\" este:" << endl;
mcopy.afisare( );
}
else cout << "Dimensiuni invalide pentru matricea care se copiaza la instantiere!" << endl;
cout << endl << "Instantiem un nou obiect matrice \"n\" ";
Matrix n(linii, coloane);
cout << endl << "Dati matricea:" << endl;
n.citire( );
cout << endl << "Matricea \"n\" este:" << endl;
n.afisare( );
cout << endl << "Supraincarcarea operatorului =, copiere matrice \"m\" in matrice \"n\"" << endl;
if (m.getRows( ) == n.getRows( ) && m.getCols( ) == n.getCols( )){
n = m;
//n.afisare( );
for (i = 0; i<linii; i++){
for (j = 0; j<coloane; j++)
cout << n(i, j) << "\t";//afisare prin Supraincarcarea operatorului( )
cout << endl;
}///end for
}
else
cout << "Matricile nu au aceleasi dimensiuni, deci nu pot fi copiate" << endl;
83
cout << endl << "Instantiem un nou obiect matrice \"m1\" ";
Matrix m1(linii, coloane);
cout << endl << "Dati matricea:" << endl;
m1.citire( );
cout << endl << "Matricea \"m1\" este:" << endl;
m1.afisare( );
/*matricea m are 2 linii si 3 coloane deci pentru a fi posibil produsul m3 trebuie sa aiba 3 linii si 2
coloane*/
cout << endl << "Dati matricea pentru produs \"m3\' (matricea trebuie sa aiba numarul de linii egal cu
numarul de coloane al matricii \"m\")" << endl;
cout << "Numar de linii: ";
cin >> l;
cout << "Numar coloane: "; 84
cin >> c;
Matrix m3;
if (l>0 && c>0) m3.init(l, c);
else cout << endl << "Dimensiuni negative (gresite)! Se vor folosi pentru
instantiere valorile initiale implicite (2 linii, 3 coloane)" << endl;
m3.citire( );
cout << endl << "Matricea \"m3\" este:" << endl;
m3.afisare( );
}//end main
85
String complete example
//StringA.h header
const int dim = 30;
class String {
char* sir;
public:
String( ) {
sir = new (nothrow) char[dim];
}
String(char* x) {
sir = new (nothrow) char[strlen(x) + 1];//se mai rezerva pentru \0 – destructorul va lucra corect
strcpy(sir, x);
}
String(const String& x) {//copy constructor
sir = new (nothrow) char[strlen(x.sir) + 1];
strcpy(sir, x.sir);
}
String& operator= (const String& x) {//assign
if (this == &x) return *this;
delete [ ] sir;
sir = new (nothrow) char[strlen(x.sir) + 1];
strcpy(sir, x.sir);
return *this;
}
~String( ) {
delete[ ]sir;
}
86
void setSir(char* x) {
sir = new (nothrow) char[strlen(x) + 1];
strcpy(sir, x); }
char* getSir( ) {
return sir; }
String operator+ (String x1) { // supraincarcare cu metoda membra
String rez;
strcpy(rez.sir, sir);
strcat(rez.sir, x1.sir);
return rez; }
//functia prietena care supraincarca operatorul de scadere este definite in exteriorul clasei mai jos
friend String operator-(const String& x1, const String& x2);
int main() {
char xx[dim];
String ob3;
char c;
cout << "\n Dati un sir de caractere (I-ul obiect), mai mic de " << dim << " :";
gets_s(xx, _countof(xx));
String ob1(xx);
cout << "\n Dati un sir de caractere (al II-lea obiect), mai mic de " << dim << " :";
cin.getline(xx, _countof(xx));
String ob2(xx);
ob3 = ob1 + ob2;//assign
cout << "\nSirul obtinut in urma adunarii: " << ob3.getSir();
cout << "\n Sirul care va fi scazut din cel initial, mai mic de " << dim << " :";
gets_s(xx, _countof(xx));
String ob4(xx);
String ob5 = ob1 - ob4;//copy constructor
cout << "\nSirul obtinut in urma scaderii: " << ob5.getSir();
c = ob5[1];
cout << "\n Al 2-lea caracter din sirul de mai sus este: " << c;
String ob6;
cout << "\n Dati un sir de caractere pentru un obiect, mai mic de " << dim << " :";
cin.getline(xx, _countof(xx));
ob6.setSir(xx);
cout << "\nSirul : " << ob6.getSir();
}//main
88