Lab2.docx

25
Ministerul Educaţiei al Republicii Moldova Universitatea Tehnică a Moldovei Catedra Automatica si Tehnologii Informationale Ingineria Sistemelor Biomedicale REFERAT La Lucrare de laborator nr.2 la disciplina: Programarea in limbajul C++ Tema: Constructorul – funcţie de iniţializare a obiectelor clasei Varianta 10 A efectuat: st. gr. ISBM-131 Moroi Ion A verificat: M. Balan

Transcript of Lab2.docx

Page 1: Lab2.docx

Ministerul Educaţiei al Republicii Moldova

Universitatea Tehnică a Moldovei

Catedra Automatica si Tehnologii Informationale

Ingineria Sistemelor Biomedicale

REFERATLa Lucrare de laborator nr.2

la disciplina: Programarea in limbajul C++Tema: Constructorul – funcţie de iniţializare a obiectelor clasei

Varianta 10

A efectuat: st. gr. ISBM-131 Moroi Ion

A verificat: M. Balan

Chişinău 2014

Page 2: Lab2.docx

1. Scopul lucrării: Studierea principiilor de definire şi utilizare a constructorilor Studierea principiilor de definire şi utilizare a destructorilor Studierea tipurilor de constructori

2. Sarcina lucrarii:Să se creeze clasa Matrix – matrice. Clasa conţine pointer spre float, numărul

de rînduri şi de coloane şi o variabilă – codul erorii. Să se definească constructorul fără parametri (constructorul implicit), constructorul cu un parametru – matrice pătrată şi constructorul cu doi parametri – matrice dreptunghiulară ş. a. Să se definească funcţiile membru de acces: returnarea şi setarea valorii elementului (i,j). Să se definească funcţiile de adunare şi scădere a două matrice; înmulţirea unei matrice cu alta; înmulţirea unei matrice cu un număr. Să se testeze funcţionarea clasei. În caz de insuficienţă de memorie, necorespondenţă a dimensiunilor matricelor, depăşire a limitei memoriei utilizate să se stabilească codul erorii.

3. Indicatii teoretice:·        Constructori Constructorii sunt metode speciale care folosesc la crearea si initializarea instantelor unei clase.·        Programatorul poate defini un constructor.·        In absenta altor definitii, clasei i se ataseaza in mod implicit un constructor. Un astfel de constructor se numeste constructor implicit.·        Constructorii impliciti nu au parametri·        Constructorii impliciti nu se genereaza in cazul in care clasa are atasat un alt constructor  (asadar constructorii impliciti sunt constructori fara parametri generati automat de limbaj daca programatorul nu si-a definit unul).·        Constructorii au acelasi nume ca si clasa careia îi apartin·        Constructorii sunt apelati de fiecare data când se creaza noi instante ale clasei.class complex{public: float x,y,m; //datele clasei void display();//metodele clasei float modul();}; float complex::modul(){return sqrt(x*x+y*y);}void complex::display(){cout<<x<<"+"<<y<<"*i";}Clasa nu are definit un constructor prin urmare este generat in mod automat un constructor implicit care va permite declararea unor instante ale clasei astfel:void main(){ complex q1; //constructorul implicit permite instantiarea clasei complex  complex *q=new complex; 

2

Page 3: Lab2.docx

  cout<<q1.x<<” „<<q1.y; //afiseaza valori reziduale  cout<<endl<<q->x<<” „<<q->y; //afiseaza valori reziduale……………..}Cum am mai spus, programatorul isi poate defini constructori proprii. Constructorii vor fi definiti ca niste functii fara tip, fara a se trece in dreptul constructorului cuvantul cheie void. Constructorul va avea acelasi nume ca si al clasei careia ii apartine.O clasa poate avea mai multi constructori, care difera între ei prin numarul si tipul parametrilor acestora. Acest lucru este posibil deoarece limbajul C++ permite supradefinirea ( supraincarcarea=overloading) functiilor.Supraîncarcarea (supradefinirea) reprezinta posibilitatea de a atribui unui nume mai multe semnificatii, care sunt selectate în functie de context. Practic, se pot defini functii cu acelasi nume, dar cu liste de parametri diferite, ca numar si/sau ca tipuri de parametri. În momentul apelului functiei, selectarea functiei adecvate se face în urma compararii tipurilor parametrilor efectivi cu tipurile parametrilor formali. De aceea, declararea unor functii cu acelasi nume si acelasi set de parametri este ilegala si este semnalata ca eroare la compilare.    La întâlnirea declararii unui obiect, se apeleaza automat un constructor al clasei respective. La fiecare instantiere a clasei se aloca memorie pentru datele membre. Deci pentru fiecare obiect declarat se aloca memorie pentru datele membre ale clasei. Functiile membru exista într-un singur exemplar pentru toate instantele clasei.Ordinea în care sunt apelati constructorii corespunde ordinii declararii obiectelor.    Proprietatile constructorilor:

Constructorii au acelati nume ca si numele clasei careia îi apartin; Nu întorc nici o valoare (din corpul lor lipseste intructiunea return; în antetul

constructorilor nu se specifica niciodata - la tipul valorii returnate - cuvântul cheie void);

Constructorii unei clase nu pot primi ca parametri instante ale unei clase, ci doar pointeri sau referinte la instantele clasei respective;

Apelul constructorului se realizeaza la declararea unui obiect; Adresa constructorilor nu este accesibila utilizatorului; Constructorii nu pot fi metode virtuale (vor fi studiate ulterior); În cazul în care o clasa nu are nici constructor declarat de catre programator,

compilatorul genereaza un constructor implicit, fara nici un parametru, cu lista instructiunilor vida. Daca exista un constructor, compilatorul nu mai genereaza constructorul implicit ;

Parametrii unui constructor nu pot fi de tipul definit de clasa al carei    {cout<<endl<<"mesaj de la constructor"<<endl;}

 

3

Page 4: Lab2.docx

    Destructori     Destructorii sunt metode ale claselor care actioneaza în sens invers, complementar, fata de constructori. Constructorii sunt folositi pentru alocarea memoriei, initializarea datelor membru sau alte operatii (cum ar fi, incrementarea unui contor pentru instantele clasei). Constructorul este apelat în momentul declararii obiectelor. Destructorul elibereaza memoria alocata de constructori. Destructorul este apelat automat, la iesirea din blocul în care este recunoscut acel obiect.    Proprietatile destructorilor

 Destructorul are acelasi nume ca si clasa a caror metoda  este;  Numele destructorului este precedat de semnul ~;  O clasa are un singur destructor;  Destructorul nu are parametri si nu returneaza nici o valoare (antetul nu

contine cuvântul cheie void, iar în corpul destructorului nu apare instructiunea return;);

 Daca programatorul nu a definit un destructor, compilatorul genereaza automat un destructor pentru clasa respectiva;

 Destructorii se apeleaza la încheierea timpului de viata a obiectelor, în ordine inversa apelurilor constructorilor;

 Obiectele dinamice nu se distrug automat, deoarece doar programatorul stie când nu mai este necesar un astfel de obiect.

Listningul programului#include <iostream>#include <conio.h>#include <math.h>#include <stdlib.h>using namespace std;

/*Codurile erorilor:1 - Insuficienta de memorie2 - Necorespondenta a dimensiunilor matricelor3 - Depasirea limitei memoriei utilizate*/

class Matrix{ int **p; int x; // Nr. coloanelor int y; // Nr. rindurilor int error; // Numarul erorii

public: // Constructor implicit Matrix() { this->error = 0;

4

Page 5: Lab2.docx

this->p = NULL; this->x = 0; this->y = 0; }

// Constructor cu un parametru, matrice patrata Matrix(int x1) { this->x = x1; this->y = x1; this->error = 0; this->p = NULL; }

// Constructor cu 2 parametri, matrice dreptungiulara Matrix(int x1, int y1) { this->x = x1; this->y = y1; this->error = 0; this->p = NULL; }

// Functia de copiere void copy(Matrix &M) { this->x = M.x; this->y = M.y; error = M.error; this->setSize(x, y); this->p = NULL; p = new int*[x]; for(int i=0; i<y; i++){ p[i] = new int[x]; } for(int i=0; i<y; i++) for(int j=0; j<x; j++) this->p[i][j]=M.p[i][j]; }

// Returneaza 1 daca matricea este ca minim x si y diferit de 0; int ok() { if(this->x>0 && this->y>0) return 1; else return 0; }

// Returnarea valorii (i, j) int gets(int i, int j) { return this->p[i][j]; }

5

Page 6: Lab2.docx

//Formarea matricei void setSize(int n, int m) { this->x = n; this->y = m; this->p = NULL; p = new int*[x]; for(int i=0; i<y; i++){ p[i] = new int[x]; } for(int i=0; i<y; i++) for(int j=0; j<x; j++) this->p[i][j]=0; }

//Setarea valorilor matriceivoid setMatrix(int n, int m)

{ int val=0; for(int i=0; i<m; i++)

for(int j=0; j<n; j++) {

cout<<"Elementul "<<"("<<i << j<<")"<<"=";

cin>>val; this->p[i][j]=val;

} }

int _x() { return this->x; }

int _y() { return this->y; }

// Modificarea valorii (i, j), nr. linii = i; nr. coloanei = j void set(int i, int j, int valoarea) { this->p[i][j] = valoarea; }

// Functia pentru afisarea matricei void view() { for(int i=0; i<_y(); i++) { for(int j=0; j<_x(); j++)

6

Page 7: Lab2.docx

cout << gets(i, j) << "\t"; cout << endl; } }

// Eliberarea memoriei, distructor ~Matrix() { for(int i=0; i<x; i++) delete[] p[i];

delete p; }};

// Functia pentru adunarea a 2 matricevoid adunarea(Matrix *M1, Matrix *M2){ if(M1->_x() == M2->_x() && M1->_y() == M2->_y()) { for(int i=0; i<M1->_y(); i++) { for(int j=0; j<M1->_x(); j++) cout << (M1->gets(i, j)+M2->gets(i, j)) << "\t"; cout << endl; }

} else cout << "Numarul de linii si coloane nu coincide" << endl << "Pentru a efectua operatia de adunare," << " este nevoie sa coincida ambele n x m a ambelor matrice.";}

// Functia pentru scaderea a 2 matricevoid scaderea(Matrix *M1, Matrix *M2){ if(M1->_x() == M2->_x() && M1->_y() == M2->_y()) { for(int i=0; i<M1->_y(); i++) { for(int j=0; j<M1->_x(); j++) cout << (M1->gets(i, j)-M2->gets(i, j)) << "\t"; cout << endl; }

} else cout << "Numarul de linii si coloane nu coincide" << endl << "Pentru a efectua operatia de scadere," << " este nevoie sa coincida ambele n x m a ambelor matrice.";}

// Functia pentru inmultirea a 2 matricevoid inmultirea(Matrix *M1, Matrix *M2){ int sum;

7

Page 8: Lab2.docx

if(M1->_x() == M2->_y()) { for(int i=0; i<M1->_y(); i++) { for(int j=0; j<M1->_x(); j++) { sum = 0; for(int k=0; k<M1->_x(); k++) sum += M1->gets(i, k)*M2->gets(k, j); cout << sum << "\t"; } cout << endl; }

} else cout << "Numarul de linii si coloane nu coincide" << endl << "Pentru a efectua operatia de inmultire," << " este nevoie sa coincida numarul liniilor M1 cu numarul coloanelor din M2";}

// Functia pentru inmultirea unei matrice cu un numarvoid inmultirea_nr(Matrix *M, int nr){ for(int i=0; i<M->_y(); i++) { for(int j=0; j<M->_x(); j++) cout << M->gets(i, j)*nr << "\t"; cout << endl; }}

Matrix M1, M2;

void menu(){ cout<<"

НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl; cout << " Matricea M1:" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 1. M1 - Crearea matricei patratice n x n" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 2. M1 - Crearea matricei n x m" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

if(M1.ok()) cout << " 3. M1 - Afisarea/Redactarea elementelor matricei" << endl;cout<<"

НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl; cout << " Matricea M2:" << endl;

8

Page 9: Lab2.docx

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 4. M2 - Crearea matricei patratice n x n" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 5. M2 - Crearea matricei n x m" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

if(M2.ok()) cout << " 6. M2 - Afisarea/Redactarea elementelor matricei" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " Functiile:" << endl;cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 7. Adunarea si Scaderea matricilor M1 si M2" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 8. Inmultirea matricei M1 cu M2" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 9. Inmultirea unei matrice cu un numar" << endl;

cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << " 0. Iesire"<<endl;cout<<"НННННННННННННННННННННННННННННННННННННННННННННННННН"<<endl;

cout << endl << endl << "** Pentru a fi accesate toate meniurile," << endl << "incarcati cu elemente ambele matrice M1, M2";}

int main(){ system("cls"); //temp(); menu(); char c; c = getch(); int n, m; Matrix M;

switch(c) { case '1': system("cls"); cout << "M1 - Crearea matricei patratice n x n" << endl << endl;

9

Page 10: Lab2.docx

cout << "Introduceti valoarea n="; cin >> n;

M1.setSize(n, n);M1.setMatrix(n, n);

cout << "Matricea patratica M1 a fost creata cu succes!"; getch(); main(); break;

case '2': system("cls"); cout << "M1 - Crearea matricei patratice n x m" << endl << endl;

cout << "Introduceti nr. de coloane n="; cin >> n; cout << "Introduceti nr. de linii m="; cin >> m;

M1.setSize(n, m);M1.setMatrix(n, m);

cout << "Matricea " << n << " x " << m << " M1 a fost creata cu succes!"; getch(); main(); break;

case '3': if(M1.ok()) { system("cls"); cout << "Afisarea matricei M1 (" << M1._x() << " x " << M1._y() << ")" << endl << endl;

M1.view();

int o; o = 0; while(!o) { o = 1; cout << endl << endl << "Pentru redactarea elementelor tastati ENTER, " << endl << "pentru a reveni in meniul principal tastati ESC" <<endl; int c; c = '0'; while(c != 27 && c != 13) c = getch();

switch(c)10

Page 11: Lab2.docx

{ case 13: // Enter system("cls"); cout << "Redactarea elementelor matricei M1:" << endl << endl;

cout << "Matricea M1: " << endl; M1.view(); cout << endl << endl;

int i, j, nr; cout << "Selectati elementul pentru redactare (i, j):" << endl; cout << "Linia i="; cin >> i; cout << endl << "Coloana j="; cin >> j;

cout << endl << "Introduceti valoarea elementului (" << i << ", " << j << ") = "; cin >> nr; if(i >= 0 && i < M1._x() && j >= 0 && j < M1._y()) { cout << endl << endl << "Valoarea a fost salvat cu succes!" << endl; M1.set(i, j, nr); } else cout << endl << endl << "EROARE! Valoarea nu a fost salvata din cauza coordanatelor gresite" << endl; cout << "Matricea arata in felul urmator: " << endl; M1.view(); o = 0; break;

case 27: // Esc main(); break; } } main(); } else main(); break;

case '4': system("cls"); cout << "M2 - Crearea matricei patratice n x n" << endl << endl;

cout << "Introduceti valoarea n="; cin >> n;

11

Page 12: Lab2.docx

M2.setSize(n, n);M2.setMatrix(n, n);

cout << "Matricea patratica M2 a fost creata cu succes!"; getch(); main(); break;

case '5': system("cls"); cout << "M2 - Crearea matricei patratice n x m" << endl << endl;

cout << "Introduceti nr. de coloane n="; cin >> n; cout << "Introduceti nr. de linii n="; cin >> m;

M2.setSize(n, m);M2.setMatrix(n, m);

cout << "Matricea " << n << " x " << m << " M2 a fost creata cu succes!"; getch(); main(); break;

case '6': if(M2.ok()) { system("cls"); cout << "Afisarea matricei M2 (" << M2._x() << " x " << M2._y() << ")" << endl << endl;

M2.view();

int o; o = 0; while(!o) { o = 1; cout << endl << endl << "Pentru redactarea elementelor tastati ENTER, " << endl << "pentru a reveni in meniul principal tastati ESC"; int c; c = '0'; while(c != 27 && c != 13) c = getch();

switch(c) { case 13: // Enter system("cls");

12

Page 13: Lab2.docx

cout << "Redactarea elementelor matricei M2:" << endl << endl;

cout << "Matricea M1: " << endl; M2.view(); cout << endl << endl;

int i, j, nr; cout << "Selectati elementul pentru redactare (i, j):" << endl; cout << "Linia i="; cin >> i; cout << endl << "Coloana j="; cin >> j;

cout << endl << "Introduceti valoarea elementului (" << i << ", " << j << ") = "; cin >> nr;

if(i >= 0 && i < M2._x() && j >= 0 && j < M2._y()) { cout << endl << endl << "Valoarea a fost salvat cu succes!" << endl; M2.set(i, j, nr); } else cout << endl << endl << "EROARE! Valoarea nu a fost salvata din cauza coordanatelor gresite" << endl; cout << "Matricea arata in felul urmator: " << endl; M2.view(); o = 0; break;

case 27: // Esc main(); break; } } main(); } else main(); break;

case '7': system("cls"); cout << "Adunarea matricelor M1 si M2" << endl << endl; adunarea(&M1, &M2);

cout << endl << endl << "Scaderea matricelor M1 si M2" << endl << endl;

13

Page 14: Lab2.docx

scaderea(&M1, &M2);

getch(); main(); break;

case '8': system("cls"); cout << "Inmultirea matricelor M1 si M2" << endl << endl; inmultirea(&M1, &M2);

getch(); main(); break;

case '9': system("cls"); cout << "Inmultirea matricei cu un numar" << endl << endl;

cout << "Selectati matricea M1 sau M2 pentru inmultire (1-2): "; char l; l = '0';

while(l != '1'&& l != '2') l = getch();

switch(l) { case '1': M.copy(M1); break;

case '2': M.copy(M2); break; }

int nr; cout << endl << "Introduceti nr. de inmultire a matricei " << l << ": "; cin >> nr;

cout << endl << "Matricea " << l << " in urma inmultirii cu " << nr << " este:" << endl; inmultirea_nr(&M, nr);

getch(); main(); break;

14

Page 15: Lab2.docx

case '0': exit(1); break;

default: main(); break; }}Afisarea rezultatelor

Meniul:

Introducerea datelor:

15

Page 16: Lab2.docx

Afisarea datelor:

Adunarea si scaderea matricilor:

16

Page 17: Lab2.docx

Inmultirea uneia din matrici cu un numar:

Inmultirea primei matrice cu a doua:

Întrebări de control:

17

Page 18: Lab2.docx

1. Explicaţi termenul de iniţializare.Initializarea unui obiect presupune si initializarea datelor membru ce descriu starea acestuia; daca un constructor asociat tipului unei date membru are parametrii avem nevoie de un mijloc pentru a specifica valorile acestora. Aici intervine lista de initializarea a constructorului care este o secventa de apeluri de constructori ai datelor membru si ai claselor din care clasa curenta este derivata.

2. Ce cuvinte cheie se utilizează pentru definirea constructorului şi a destructorului?3. Poate oare un constructor să returneze o valoare?

Constructorul nu poate returna valori.4. Pot oare să existe clase fără constructori?

Chiar daca constructorul nu este declarat, el este generat in mod implicit de catre compilator.

5. Cîţi constructori poate conţine o clasă? Dar destructori? De ce?O clasa poate contine mai multi constructori, dar nu putem spune acelasi lucru despre destructori, care intr-o clasa este exclusiv numai unul. Constructorii sunt folositi pentru alocarea memoriei, initializarea datelor membru sau alte operatii (cum ar fi, incrementarea unui contor pentru instantele clasei). Constructorul este apelat în momentul declararii obiectelor. Destructorul elibereaza memoria alocata de constructori. Destructorul este apelat automat, la iesirea din blocul în care este recunoscut acel obiect.

6. Enumeraţi tipurile de constructori? Constructorul implicit – constructor fără parametri, sau constructor cu toţi parametrii impliciţi. Constructorul de copiere – constructor care are ca parametru referinţă la obiectul clasei

respective. Constructorul de copiere poate avea şi alţi parametri care însă trebuie să fie impliciţi.

Constructorul de conversie a tipului - constructorul, care transformă un tip de obiect în altul. Constructorul general – constructorul care nu corespunde categoriilor enumerate mai sus.

7. Cum se apelează un constructor?8. De ce este nevoie de definit un constructor de copiere?

Dacă clasa conţine elemente pointeri trebuie neapărat să se supraîncarce constructorul de copiere, care se utilizează pentru crearea copiilor obiectului, la apelul obiectului în funcţie. Motivul supraîncărcării constructorului de copiere constă în necesitatea utilizării acţiunilor suplimentare în comparaţie cu algoritmul standard de copiere, deoarece se poate întîmpla ca două obiecte diferite să refere una şi aceeaşi memorie, ceea ce poate duce la pierderea informaţiei şi la erori în sistemul de operare.

9. De ce este nevoie de definit un constructor de conversie a tipului?Pentru evitarea erorilor dintre tipurile de variabile (float, double, int etc). De asemenea constructorul de conversie nu permite conversia de la un tip fundamental la un tip clasa.

10. În ce cazuri se apelează constructorul de copiere? Care este sintaxa apelului?Daca clasa contine elemente pointeri.In cazul in care două obiecte diferite se refera la una şi aceeaşi memorie.

#include<math.h>#include<iostream.h>

18

Page 19: Lab2.docx

#include<conio.h>

class complex{public: float x,y,m; //datele clasei void display(); float modul(); //metoda clasei complex(float xx=0, float yy=0) {cout<<endl<<"mesaj de la constructorul cu parametri impliciti "<<endl; x=xx; y=yy; } complex(complex &ob) //constructor de copiere { cout<<endl<<"operatie de copiere "; x=ob.x; y=ob.y; } }; float complex::modul(){return sqrt(x*x+y*y);} void complex::display(){cout<<endl<<x<<"+"<<y<<"*i";cout<<endl;} void main(){complex q1(1.2,1.3);cout<<"q1=";q1.display();complex q2=q1; //se apeleaza constructorul de copierecout<<"q2=";q2.display();complex q3=complex(q1); //se apeleaza constructorul de copiere cout<<"q3=";q3.display();getch();clrscr();}

11. Ce sunt listele de iniţializare (iniţializatori)?

19

Page 20: Lab2.docx

Initializarea unui obiect presupune si initializarea datelor membru ce descriu starea acestuia; daca un constructor asociat tipului unei date membru are parametrii avem nevoie de un mijloc pentru a specifica valorile acestora. Aici intervine lista de initializarea a constructorului care este o secventa de apeluri de constructori ai datelor membru si ai claselor din care clasa curenta este derivata. Lista de initializare a constructorului urmeaza imediat dupa lista de parametrii ai constructorului separata prin intermediul delimitatorului ":" . Apelurile de constructori din cadrul listei de initializare sunt separate prin ";"

12. În care caz se defineşte obligatoriu constructorul implicit?Cind constructorul nu a fost declarat in clasa de catre programator.

Concluzie: In urma efectuarii acestei lucrari de laborator capatat cunostinte despre modul de lucru cu clasele in limbajul c++, am capatat cunostinte despre modul de formare a constructorilor si destructorilor unei clase.

20