POO - Lab. 1 Elemente specifice C++ fara clase 1) Comentarii "stil" C++ Putem scrie comentarii pe o linie prin simbolurile // Ce este intre // si sfirsitul liniei se ignora 2) Structurile si uniunile pot fi referite doar prin nume Dupa o definitie de forma: struct str { ......}; union uni {.....}; putem scrie: str a, b; uni c, d; void f(str x) {......} deci fara a fi nevoie sa utilizam cuvintele cheie struct sau union de fiecare data. Aceasta arata ca structurile si uniunile sint in C++ automat tipuri de date recunoscute. 3) Functii inline O functie definita prin: inline TIP nume (lista argumente) se numeste functie inline. La apelul sau, in loca sa se apeleze pr.-zis functia, se substituie codul generat de fiecare data. Este similar cu efectul unei macroinstructiuni, cu deosebirea importanta ca MI se substituie in textul sursa, inainte de compilare, iar functia inline in textul obiect, la compilare. // Exemplu inline int max (int a, int b) { return (a>b) ? a : b; } De comparat cu MI din C similara: #define max(a,b) (((a) > (b)) ? (a) : (b)) 4) Supradefinirea functiilor In C++ este permisa supradefinirea functiilor, adica existenta mai multor functii cu acelasi nume, dar care difera prin tipul si/sau numarul parametrilor. Decizia de a apela o functie sau alta se face dupa tipul sau numarul parametrilor. Aceasta inseamna ca o functie este recunoscuta nu numai prin numele sau ci prin "semnatura", adica nume, tip si lista de parametri. In exemplul de fata, se considera patru functii cu acelasi nume (cub). Trei dintre ele au un unic parametru (int, float si double), iar a patra are doi parametri. Ultima functie apeleaza functia cub specifica tipului float. Pentru a urmari apelurile, fiecare functie este insotita de un mesaj de identificare la consola. int cub (int n) { cout << "Apel functie cub int\n"; return n*n*n; } double cub (double n) { cout << "Apel functie cub double\n"; return n*n*n; } float cub (float n) { cout << "Apel functie cub float\n"; return n*n*n; } float cub (float x, float a) { cout << "Apel functie cub diferenta\n"; return cub (x-a); // Aici se va apela cub cu float } 5) Operatorii de scriere/citire >> si << Prin acesti operatori se pot face scrieri si citiri la consola in formate predefinite. Aceasta ne scuteste de folosirea functiilor de tip printf/scanf etc. si ofera o forma comoda de I/O. Comanda #include trebuie sa fie prezenta in fisierele sursa care folosesc I/O de acest tip. // // Test << si >> // cout << "Introduceti 3 intregi:\n"; cin >> i >> j >> k; cout << "Intregii sunt:\n"; cout << i << " " << j << " " << k << "\n"; 6) Tipul referinta O declaratie de forma: int x; int &y = x; precizeaza ca y este o referinta catre un intreg (catre x). Din punct de vedere sintactic, y este tot un intreg, care nu "exista" insa (nu are suport propriu de memorie) ci este o alta referire la variabila x. Utilitatea principala a referintelor este impunerea transferului prin referinta a parametrilor la o functie. Acest fapt este ilustrat prin functia schimba de mai jos. void schimba (int & a,int & b) { int temp = a; a = b; b = temp; } Declaratiile de parametri spun ca a si b sunt referinte catre intregi, deci la un apel de forma: int x = 7, y = 3; schimba (x, y); in variabilele a si b din functie se vor gasi referinte catre intregii x si y din programul apelant. Aceasta face ca functia sa poata modifica efectiv aceste variabile. De comparat cu metoda de implementare a transferului prin referinta la C standard, unde trebuiau utilizati explicit pointeri: void schimba_C (int * a, int * b) { int temp = *a; *a = *b; *b = temp; } cu apelul: int x = 7, y = 3; schimba_C (&x, &y); 7) Alocari dinamice de memorie Alocarea de memorie se face in C++ cu operatorul new (care face parte din limbaj). Exista forma de alocare simpla, forma cu initializarea spatiului alocat si forma de alocare pentru un tablou. Se utilizeaza pointeri adecvati. Daca se doreste o alocare oarecare (fara a avea un tip precizat), se poate folosi tipul char (adica alocare la nivel de octet), sau unsigned char, "botezat" eventual cu typedef. 8) Functii cu parametri impliciti Functia print_tab de mai jos are trei parametri, dintre care ultimul este de tip pointer la char, care este initializat implicit pe sirul constant "Mesaj implicit". Functia se poate apela cu un parametru explicit, sau ca si cind ar fi doar cu doi parametri, caz in care se va utiliza al treilea parametru implicit. // // Test functie cu argument implicit // print_tab (q, 10, "Mesaj explicit\n"); print_tab (q, 10); 9) Tema Definiti cu typedef tipul VECTOR (vector de 3 numere reale) si tipul MATRICE (matrice 3 X 3 de numere reale). Scrieti diverse functii, toate cu numele produs, care sa realizeze: -produsul dintre un vector si un scalar; -produsul dintre o matrice si un scalar; -produsul (scalar) dintre doi vectori; -produsul dintre o matrice si un vector (rezultat = vector); -produsul a doua matrici; */ #include int cub (int n) { cout << "Apel functie cub int\n"; return n*n*n; } double cub (double n) { cout << "Apel functie cub double\n"; return n*n*n; } float cub (float n) { cout << "Apel functie cub float\n"; return n*n*n; } float cub (float x, float a) { float m; cout << "Apel functie cub diferenta\n"; return cub (x-a); // Aici se va apela cub cu float } void schimba (int & a,int & b) { int temp = a; a = b; b = temp; } void print_tab (int *a, int n, char *mesaj = "Mesaj implicit\n") { for (int i = 0; i < n; i++) cout << a[i] << " "; cout << "\n" << mesaj; } void main(void) { int i = 12; float f = 12.5F; double d = 12.5; int j = 21, k; int *p, *q; // // Test functii cub // cout << cub(i) << " " << cub (f) << " " << cub (d) << "\n"; cout << cub (f, 2.5) << "\n"; cout << "i = " << i << " j = " << j << " inainte de schimba(i,j)\n"; schimba (i, j); cout << "i = " << i << " j = " << j << " dupa schimba(i.j)\n"; // // Test << si >> // cout << "Introduceti 3 intregi:\n"; cin >> i >> j >> k; cout << "Intregii sunt:\n"; cout << i << " " << j << " " << k << "\n"; // // Test operatori new si delete // p = new int; *p = 30; // Alocare simpla cout << *p << "\n"; delete p; p = new int (100); // Alocare cu initializare cout << *p << "\n"; delete p; q = new int [10]; // Alocare tablou de 10 int for (i = 0; i < 10; i++) *(q + i) = i + 1; for (i = 0; i < 10; i++) cout << q[i] << " "; cout << "\n"; // // Test functie cu argument implicit // print_tab (q, 10, "Mesaj explicit\n"); print_tab (q, 10); delete [] q; // Eliberare tablou // // La compilatoarele mai vechi, eliberarea de tablouri (i.e. operatorul delete []) nu este posibila. // Se foloseste in acest caz delete simplu. // }