0% found this document useful (0 votes)
3 views88 pages

An1 Sem2 Curs7 Eng Over

The document discusses function and method overloading in C++, covering the rules and principles for overloading based on parameter types and counts. It explains operator overloading, including the types of operators that can be overloaded and the implications for class design. Additionally, it addresses type conversions and how to handle binary operators with different operand types, providing examples of how to implement these concepts in a Complex class.

Uploaded by

roxy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views88 pages

An1 Sem2 Curs7 Eng Over

The document discusses function and method overloading in C++, covering the rules and principles for overloading based on parameter types and counts. It explains operator overloading, including the types of operators that can be overloaded and the implications for class design. Additionally, it addresses type conversions and how to handle binary operators with different operand types, providing examples of how to implement these concepts in a Complex class.

Uploaded by

roxy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 88

Computer programming -

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;
}

int myFunction(int x, int y){


return x*y;
2
}
• When only the return value is different, the compiler will not
accept more functions with the same name and parameters being
important how the functions are called:
int myFunction(int x);
double myFunction(int x);
cout << myFunc(10);//ambiguities- double or int return are not
significant
• The compiler will not make a distinction between a parameter
transferred by value and by reference. In one of the case a
redundant extra parameter will be used:
int myFunction(int x){
return x;
}
int myFunction(int &x, int a){//extra redundant parameter
return x;
}
cout << myFunc(10);// no ambiguities- first function, x by value
cout << myFunc(10, 0);// no ambiguities- second function, x by
reference
3
Overloading ambiguities

• The automated type conversion will introduce


ambiguities in C++:
float myFunc(float i);
double myFunc(double i);
–Call:
cout << myFunc(1.9);// no ambiguities- double
cout << myFunc(10);// with ambiguities, any
int/float/double as parameter function should be used

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

• This is because we have no-overlapping visibility domains


in these cases

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));

We can write by overloading operators for Complex type


objects in a simply mode, so:
e = (a+b)*(c-d) ; 6
• By overloading, do not lose any of the initial roles
and functions of the operators
• In C++, almost all operators can be overloaded in their
classes so that their use with instances of these classes,
will have the established role specified by the user, and
not the default role.
• The following operators are not possible to be
overloaded:
– . (point)
– :: (resolution)
– ?: (conditional)
– * (indirection)
– sizeof( )
– (++, --) increment/decrement, initial was not possible
to be overloaded, now, yes, as post/prefix operators
7
Operators possible to be
overloaded
• + - * / = < > += -= *= /=
<< >> <<= >>=
• == != <= >= ++ -- % & ^ ! |
~ &= ^= |= && || %= [ ] ( ) , ->*
->
• new delete new[ ] delete[ ]

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

• Operator methods do not allow parameters with default values


• Operators overloaded in the derived class hide other overloads of
the same operators in the base class

• Except for the assignment operator (=) that it is not inherited,


by derivation, it is possible to inherit the other base class
overloaded operators
10
Overloading operators with
methods (member functions)
• Number of arguments it is equal to the number of
operands minus one:
- The first operand is referenced by this pointer by
default, and represents the current object
- Unary operators have no arguments
- Binary operators have one argument
• General form:
return_type Class_name::operator#(arguments_list)
{
// operations
}
- The # symbol is a reserved symbol for the operator to be
11
overloaded
Example:
//Complex.h

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; }*/

Complex Complex :: operator-(Complex x) {


Complex rez;
rez.im = im - x.im;
rez.re = re - x.re;
return rez; }

/* Complex * Complex :: operator-(Complex *x) {


Complex *rez = new (nothrow) Complex;
rez->im = im - x->im;
rez->re = re - x->re;
return rez;
}*/
Complex & Complex :: operator+(const Complex &x) {
Complex &rez = *new (nothrow) Complex(re + x.re, im + x.im);
return rez;
} 13
#include <iostream>
using namespace std;
#include "Complex.h"

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:

friend return_type operator#(arguments_list) ;

- The # symbol is a reserved symbol for the operator to be


overloaded
15
Example:
//Complex.h
class Complex {
double re, im;
public:
Complex(double x = 0., double y = 0.) {
re = x;
im = y; }
double getRe( ){
return re;}
double getIm( ){
return im;}
//friend Complex operator+(Complex x, Complex y);
friend Complex operator-(Complex x, Complex y);
friend Complex & operator+(const Complex &, const Complex &);
};//Complex class
16
/*Complex operator+(Complex x, Complex y) {
Complex rez;
rez.re = x.re + y.re;
rez.im = x.im + y.im;
return rez;
}*/
Complex operator-(Complex x, Complex y) {
Complex rez;
rez.re = x.re - y.re;
rez.im = x.im - y.im;
return rez;
}
//with references
Complex & operator+(const Complex &x, const Complex &y){
Complex *t;
t= new (nothrow) Complex(x.re+y.re, x.im+y.im);
return *t;
}
17
#include <iostream>
using namespace std;
#include "Complex.h"

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->( ) -

• Remark: Increment/decrement operators, ++/--, can be


pre-fixed and post-fixed. If are postfixed, we add a
redundant extra parameter to distinguish the signatures.20
Type conversions
• C/C++ compilers automatically performs data conversions
for different data types (implicit conversion rule).
• These conversions may occur:
a) applying an operator to operands of different types
b) the actual parameter of a method/function type is different
from the corresponding formal parameter
c) the return type from the header of the method/function is
different from that of expression in the return statement.
• The user can in certain circumstances to require conversion
with explicit cast operator. It can be used in C++, no
templates, as follows:
(type_cast) expression
or,
type_cast (expression)
21
• If it comes to overload binary operators with operands of
different types, we have the following solutions:
-to overload operator for operands of different types
-to convert the predefined operand to the abstract type and then
apply an overloaded operator for abstract type. Sometimes this
process is not possible.
class Complex { …
public:
friend Complex operator+(Complex , Complex);
//Complex operator+(Complex);
friend Complex operator+(Complex , double);
//Complex operator+(double);
friend Complex operator+(double, Complex);
//no equivalent with methods
};//class

• In this class to provide the addition between a Complex object


type and a double, it is provided two friend operator functions
(overloaded functions) that are practical equivalent as
implementation but different as signature:
22
Complex operator+(double a, Complex c)
{
Complex rez;
rez.re=a+c.re;
rez.im=c.im;
return rez;
}
Complex operator+(Complex c, double a)
{
Complex rez;
rez.re=c.re+a;
rez.im=c.im;
return rez;
}
/* Equivalent method overloading
Complex Complex :: operator+(double a) {
Complex rez;
rez.re = re + a;
rez.im = im;
return rez;
} */
• You can use a constructor (conversion) to convert the predefined involved
23
type in an object of the class:
class Complex {double re, im;
public:
Complex( ) = default;//undefined values for double attributes
Complex(double x) {
re = x;
im = 0.;
}
Complex(double x, double y) {
re = x;
im = y;
}

friend Complex operator+( Complex c1, Complex c2);
};//class

Following a single operator function is sufficient and are possible expressions


that involves operands of Complex type and int operands:

Complex z(5.,6.), q;
q= z + 5.; // equivalent with: q = operator+(z, Complex(5.));
Other variant will consider a type conversion method – overloading cast operator:
operator type_Name ( ) {
// cast body method
}
Such a method will convert an object of the current class to type_Name during the24
explicit conversion (cast).
//Complex.h – constructor conversion or + operator overloading for double
class Complex {
double re, im;
public:
Complex( ) = default;//re, im, undefined as double values
Complex(double x) {//conversion double to Complex
re = x;
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+(double);//if no Complex(double x)
Complex operator-(Complex x);
};//Complex class
Complex Complex :: operator+(Complex x) {
Complex rez;
rez.re = re + x.re;
rez.im = im + x.im;
return rez; }
/*Complex Complex :: operator+(double a) {
Complex rez;
rez.re = re + a;
rez.im = im;
return rez;}*/
Complex Complex :: operator-(Complex x) {
Complex rez;
rez.re = re - x.re;
rez.im = im - x.im;
return rez;}
25
//main
#include <iostream>
using namespace std;
#include "Complex.h"
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;
//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 z(5., 6.), q;
q = z + 5.; // equivalent with: q = operator+(z, Complex(5.));
cout << "\nSum result of q: " << q.getRe() << " +i* " << q.getIm() <<
endl; 26
}//main
//Point_rectangle.h as header file
class Point {
private:
int x, y;
public:
Point(int x, int y) { Point::x = x; this->y = y; }
Point(int x) { Point::x = Point::y = x; } //type conversion constructor

friend Point operator+(Point p, Point q);


friend Point operator-(Point p, Point q);
void print( ) { cout << "(" << x << "," << y << ")"; }
};//Point class

Point operator+(Point p, Point q) {


return Point(p.x + q.x, p.y + q.y);
}
Point operator-(Point p, Point q) {
return Point(p.x - q.x, p.y - q.y);
}

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) { }

operator Point( ) {//cast overloading to Point


return botRight - topLeft;
}
friend Rectangle operator+(Rectangle &r, Rectangle &t);
friend Rectangle operator-(Rectangle &r, Rectangle &t);

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

a) Conversion of predefined default type -> in abstract type


is done automatically by calling a suitable conversion
constructor. The constructor will have as parameters that
default parameter type, and it is possible other parameters
that should be all implicit.

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;
}

The operator method must be a class member function (a class method - no


global extern, no friend function) and it is not inherited.
• There is a distinction between assignment and initialization, for both
operations using the symbol =
- The symbol = appears in initialization statement (new object obtained
that does not exist), initialization is performed using the copy
constructor:
Type Ob2(Ob1);//Ob2 does not exist and will be generated and
init with Ob1 with copy constructor
Type Ob2 = Ob1;//init with copy constructor, Ob2 does not exist34
• When the symbol = appears in an expression where we
are dealing with an assignment (both objects are already
defined) we use a variant of the overloaded assignment
operator (by default or by user):
Type Ob1, Ob2;// objects instantiation

Ob2 = Ob1;//assign operation

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];
}

Array(const Array& a) {//copy constructor


length = a.length;
arr = new (nothrow) double[length];
for (int i = 0; i < length; i++) *(arr + i) = a.arr[i];
cout << "\nCopy cons.\n"; }
Array(Array&& a) noexcept {//move constructor
arr = a.arr;
length = a.length;
cout << "\nMove cons.\n";
a.arr = nullptr;
a.length=0; }
Array& operator= (const Array& a) {//assign overloading
if (this == &a) return *this;
//this->~Array( );//if destructor defined, and more attributes allocated dynamically
delete[ ] arr;
length = a.length;
arr = new (nothrow) double[length];
for (int i = 0; i < length; i++) *(arr + i) = a.arr[i];
cout << "\nOverload assign\n"; 36
return *this; }
void setLength(int number) {
length = number;
}
int getLength() {
return length;
}
void setArr(double* t_array) {
for (int i = 0; i < length; i++)
*(arr + i) = *(t_array + i);
}
void displayArray() {
for (int i = 0; i < length; i++)
cout << arr[i] << " ";
}
Array difArray(Array ob, int l) {
Array dif_array(l);
for (int i = 0; i < l; i++)
dif_array.arr[i] = arr[i] - ob.arr[i];
return dif_array;
}
Array difArrayM(Array ob) {//move constructor
int dim = this->length > ob.length ? ob.length : this->length;
ob.length = dim;
for (int i = 0; i < dim; i++)
ob.arr[i] = ob.arr[i] - arr[i];
return ob;
}
~Array() {
if (arr != nullptr)cout << "\nCall Destructor\n";
else cout << "\nDestructor is called for nullptr\n";
delete[ ] arr;
} 37
};//Array
//main
#include<iostream>
using namespace std;
#include "Array.h"

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;
}

// overloading assign operator


String& operator = (const String &x)
//String operator=(const String &obj);
//String operator=(char *s);

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);

// overloading operator- (subtraction)


// String operator-(String &obj); // with member method
friend String operator-(String &obj1, String & obj2);
String operator-(char *s);

44
// overloading relational operators (compare current object with
another object)

int operator==(String &obj)


{ return !strcmp(p, obj.p); }
int operator!=(String &obj)
{ return strcmp(p, obj.p); }
int operator<(String &obj)
{ return strcmp(p, obj.p) < 0; }
int operator>(String &obj)
{ return strcmp(p, obj.p) > 0; }
int operator<=(String &obj)
{ return strcmp(p, obj.p) <= 0; }
int operator>=(String &obj)
{ return strcmp(p, obj.p) >= 0; }
45
// overloading relational operators (compare current object with
another object)

int operator==(char *s)


{ return !strcmp(p, s); }
int operator!=(char *s)
{ return strcmp(p, s); }
int operator<(char *s)
{ return strcmp(p, s) < 0; }
int operator>(char *s)
{ return strcmp(p, s) > 0; }
int operator<=(char *s)
{ return strcmp(p, s) <= 0; }
int operator>=(char *s)
{ return strcmp(p, s) >= 0; }

46
int strsize(void)
{ return strlen(p); }
char* makestr(char *s)
{ return strcpy(p, s); }
operator char *(void)
{ return p; }
}; // clasa String

String& String::operator = (const String &x){//assign overloading


if( this == &x) return *this;
delete [ ] p;// this-> ~String();
p = new (nothrow) char[strlen(x.p)+1];//+1 for \0
strcpy(p,x.p);
return *this;
}

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; }

void *operator new(size_t marime);


void operator delete(void *p);
};//class

void *Pozitie :: operator new(size_t marime) {


cout<<"\n Overloading local operator new with malloc";
return malloc(marime);
}
55
void Pozitie :: operator delete(void *p) {
cout<<"\n Overloading local operator delete with free";
free(p); }
//main
#include <iostream>
using namespace std;
#include "Pozitie.h"

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);

static union Block {


int xy[2];//keep coordinates
Block* next;//or the address of next free location
} *blocks;
void show1() {
cout << "\nNew point: " << "(" << xVal << "," << yVal << ")";
}
static void show2() {
cout << "\nBlocks used : " << used << ", Points alocated : " << cnt << endl;
}

static Block* freeList;//list address with free locations


static int used;//no. used locations
static int cnt;// no. created objects
};//Point class

Point::Block* Point::blocks = new (nothrow) Block[maxPoints];//global new


//static attributes alloc and init
Point::Block* Point::freeList = 0;
int Point::used = 0;
57
int Point::cnt = 0;
void* Point::operator new (size_t bytes) {
Block* res = freeList;
cout << "\nmy new called";
return (used < maxPoints) ? (cnt++, &(blocks[used++])) : (res == 0 ? 0 : (cnt++, freeList = freeList-
>next, res));
}
void Point::operator delete (void* ptr, size_t bytes) {
cout << "\nmy delete called";
((Block*)ptr)->next = freeList;
freeList = (Block*)ptr;
cnt--;
}
//main
#include <iostream>
using namespace std;
#include "Point.h"

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;

for (int i = len - 1; i >= 0; --i)


if (*bits++ == '1')vec[i/8] |= (1 << (i%8)); }
BitVec::BitVec (const short dim){
bytes = dim / 8 + (dim % 8 == 0 ? 0 : 1);
vec = new (nothrow) uchar[bytes];
for (int i = 0; i < bytes; ++i)
vec[i] = 0; }
BitVec::BitVec (const BitVec &v){//copy constructor
bytes = v.bytes;
vec = new (nothrow) uchar[bytes];
for (int i = 0; i < bytes; ++i)
vec[i] = v.vec[i];
}
62
BitVec& BitVec::operator= (const BitVec &v){//assign overloading
int i;
if (this != &v) {
for (i = 0; i < (v.bytes < bytes ? v.bytes : bytes); ++i)
vec[i] = v.vec[i];
for (; i < bytes; ++i)
vec[i] = 0;
}
return *this;
}
inline int BitVec::operator [ ] (const short idx){
return vec[idx/8] & (1 << idx%8) ? 1 : 0;
}
void BitVec::print(void){
cout <<"\nBytes in hexa are: "<<endl;
for(int i=0; i<bytes; i++)
cout <<"\nByte: "<< (i+1)<< hex <<": "<< (int)vec[i] << endl;
} 63
#include <iostream>
using namespace std;
#include "BitVec.h"

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

char * Dictionar::operator [ ](const char *pCuv){


Assoc *pAssoc;
for(pAssoc = &dict[next-1]; dict <= pAssoc; pAssoc--)
if(strcmp(pCuv, pAssoc->cuvant) == 0)
return pAssoc->definitie;
return 0;
}//[ ] 66
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include "Dictionar.h"

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

Analize t(nr); //create object of type Analize


t.introdu( ); // read data
t[g]->tip( ); // display by weight g
t[n]->tip( ); // display by name n
t[i]->tip( ); // display by index i in array
}//main
71
Overloading calling methods
operator, ( ) - iterators
• Overloading this operator is used to obtain an iterator:
- It will travers sequentially a collection
- Usually, you create an iterator class associated with the
collection class that the iterator will travers
• By overloading this operator, a behavior like this will be
obtained:
• a(b,…)  a.operator( )(b,…);
• The overloading is realized only with member methods

Example: in the Matrix class, we add this overloading


operator to access an element from the matrix:
int& operator( ) (const short row, const short col); 72
• // Example Matrix class, Matrix.h header
class Matrix {
private:
const short rows;
const short cols;
int *elems;//linear storage
// int **matrix; //pointers to raw storage
public:
Matrix(const short rows, const short cols);
Matrix(const Matrix&);//copy_constructor
~Matrix ( ) {delete [ ] elems;}
int& operator( ) (const short row, const short col);
Matrix& operator=(const Matrix&);//assign
// void displayMatrix();
const short getRows ( ){ return rows; }
const short getCols ( ){ return cols; }
};//class 73
/*for storage with int ** matrix
Matrix::Matrix(int rows, int cols) : rows(rows), cols(cols) {
matrix = new (nothrow) int* [rows];
for (int i = 0; i < rows; ++i) {
matrix[i] = new (nothrow) int[cols];
for (int j = 0; j < cols; ++j)
matrix[i][j] = 0;
}
}
Matrix::~Matrix() {
for (int i = 0; i < rows; ++i)
delete[ ] matrix[i];
delete[ ] matrix;
}
void Matrix::displayMatrix() const {
cout << "Matrix elements:" << endl;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j)
cout << matrix[i][j] << " ";
cout << endl;
}
} */ 74
Matrix::Matrix (const short r, const short c) : rows(r), cols(c)
{
//to do outside if (rows > 0 && cols > 0)
elems = new (nothrow) int[rows * cols];
}

Matrix::Matrix (const Matrix &m) : rows(m.rows), cols(m.cols)


{
int n = rows * cols;
//to do outside if (rows > 0 && cols > 0)
elems = new (nothrow) int[n];
for (int i = 0; i < n; i++)
elems[i] = m.elems[i];
}

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& Matrix::operator= (const Matrix &m)//assign operator


{
if (this != &m) {
delete [ ] elems;//this->~Matrix();
rows=m.rows; cols=m.cols;
int n = rows * cols;
elems = new (nothrow) int[n];
for (register i = 0; i < n; i++)
elems[i] = m.elems[i];
}
return *this;
} 76
#include <iostream>
using namespace std;
#include "Matrix.h"
int main ( ){
int i, j;
Matrix m(2,3);
m(0,0) = 10; m(0,1) = 20; m(0,2) = 30;
m(1,0) = 15; m(1,1) = 25; m(1,2) = 35;

for(i=0; i<2; i++) {


cout<<endl;
for(j=0; j<3; j++)
cout<<m(i, j)<<"\t";
}

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];
}

void Matrix::init(int r, int c) {


rows = r;
cols = c;
elems = new (nothrow) int[rows*cols];
}

int& Matrix:: operator( )(int row, int col)


{
return elems[row*cols + col];
}//op( )

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*/

Matrix Matrix::operator+(Matrix &p) {


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) + elems[r*cols + c];
return m;
}//op+ method 80
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-
Matrix operator*(Matrix &p, Matrix &q) {
Matrix m(p.rows, q.cols);
for (int r = 0; r < p.rows; ++r)
for (int c = 0; c < q.cols; ++c) {
m(r, c) = 0;
for (int i = 0; i < p.cols; ++i)
m(r, c) += p(r, i) * q(i, c);
}
return m;
}//op*
void Matrix::citire( ) {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
cout << "Enter elem. [" << i << "][" << j << "] ";
cin >> elems[cols*i + j]; }
}//citire
void Matrix::afisare( ) {
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
cout << elems[cols*i + j] << "\t";
cout << endl; }
}//afisare

81
//main
#include<iostream>
using namespace std;

const int linii = 2;


const int coloane = 3;

#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";

for (int i = 0; i<linii; i++)


for (int j = 0; j<coloane; j++)
m(i, j) = i + (j + 1) * 10;

for (i = 0; i<linii; i++)


{
for (j = 0; j<coloane; j++)
cout << m(i, j) << "\t";
cout << endl;
}

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( );

Matrix m2(linii, coloane);


cout << endl << "Supraincarcarea operatorului +" << endl;
if (m.getRows( ) == m1.getRows( ) && m.getCols( ) == m1.getCols( )){
m2 = m + m1;
cout << endl << "Matricea rezultata din suma matricilor m+m1 este: " << endl;
}
m2.afisare( );
cout << endl << "Supraincarcarea operatorului - " << endl;
if (m.getRows( ) == m1.getRows( ) && m.getCols( ) == m1.getCols( )){
m2 = m - m1;
cout << endl << "Matricea rezultata din diferenta matricilor m-m1 este: " << endl;
}
m2.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( );

cout << endl << "Supraincarcarea operatorului * ";


// pentru inmultire m*m3 nr. de coloane al matricii m trebuie sa fie egal cu numarul de
randuri al matricii m3
if (m.getCols( ) == m3.getRows( ))
{
Matrix m4(m.getRows( ), m3.getCols( ));
m4 = m*m3;
cout << endl << "Matricea rezultata prin inmultirea matricilor m*m3 este: " << endl;
m4.afisare( );
}
else
cout << endl << "Matricile nu pot fi inmultite - numarul de linii nu e egal cu numarul de
coloane";

}//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);

char operator[ ](int poz) { // supraincarcarea op [ ] pt. returnarea unui


char rez; // caracter din pozitia data in sir
rez = sir[poz];
return rez; }
};//class

// supraincarc. op. prin f-ctie friend, in exteriorul clasei


String operator-(const String& x1, const String& x2) {
char* pp;
pp = strstr(x1.sir, x2.sir); // adresa unde începe sirul x2.sir in sirul x1.sir
if (pp == NULL) // sirul nu se gaseste in x1.sir
return String(x1.sir);
else {
char buf[dim];
strncpy(buf, x1.sir, pp - x1.sir);
strcpy(buf + (pp - x1.sir), pp + strlen(x2.sir));
return String(buf);
}
} 87
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include "StringA.h"

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

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy