C++ POO Lab Lucrarea 2
După parcurgerea acestei platforme, veți deveni familiari cu diferite concepte de programare orientată pe obiecte.
Noțiuni despre paradigme de programare
De la inventarea mașinilor de calcul, lupta pentru performață și avans tehnologic s-a dat pe două fronturi. Pe de o parte prin îmbunătățirea performațelor hardware-ului, prin creșterea frecveței, a numărului de core-uri, a memoriei disponibile și a complexității setului de instrucțiuni, iar pe de altă parte, prin găsirea de noi metode de programare eficientă a algoritmilor. Aceste metode noi nu însemnă exclusiv limbaje noi, cu toate că dacă urmărim evoluția acestora în ultimii ani, vom observa o creștere semnificativă, atât ca număr, cât și ca varietate. De ce apar în continuare limbaje noi, dacă există deja un număr atât de mare? Există mai multe motive, dar cel principal constă în apariția unor funcționalități noi, care trebuie exprimate în moduri care încă nu există (spre exemplu acceleratoarele SIMD - Single Instruction Multiple Data sunt greoi de programat folosind C, deoarece limbajul nu are suport pentru tipuri de date vectoriale). Dar apariția limbajelor noi mai este influențată de un lucru, și anume apariția unor noi paradigme.
Paradigma de programare se referă la modul în care este descris un algoritm. Sigur, prin descriere nu ne referim la modul în care se fac adunările sau înmulțirile sau la limbajul în sine, ci la un nivel mai înalt, și anume la cum sunt structurate datele, și la legătura dintre structurile de date și secvențele de program care acționează asupra lor. Există un număr relativ mic de paradigme de programare, și vom numi imediat niște exemple, dar e important de reținut că nu se poate spune că una este sau nu mai bună decât cealaltă, ci, ca și în cazul limbajelor de programare, fiecare este optimă pentru anumite clase de aplicații.
Programarea imperativă procedurală
Programarea imperativă descrie un algoritm la nivel de instrucțiune care modifică starea programului. Programarea procedurală structurează aceste instrucțiuni pe secvențe distincte, numite proceduri sau funcții (a nu se confunda totuși cu programarea funcțională), care acționează asupra unor structuri de date globale, vizibile tuturor procedurilor, sau locale, vizibile fiecărei proceduri în parte. Ca exemplu de limbaj de programare procedural este C-ul original (nu C++). Programele scrise în C sunt construite din funcții (care pot lua argumente, calcula și întoarce valori) și date globale.
Programarea procedurală se folosește pe scară largă în programare la nivel foarte jos (kernel, sistem de operare, embedded), deoarece C-ul oferă control absolut asupra resurselor hardware, și se potrivește foarte bine cu modul în care procesorul execută programul. Pe de altă parte, în cazul aplicațiilor la nivel înalt, cum ar fi editoare de text, aplicații client - server, simulatoare, programe de sinteză, etc., acolo unde se scrie o cantitate enormă de algoritmi, faptul că programarea procedurală nu oferă o structurare a datelor și o legătură între date și procedurile care le folosesc, o face foarte greu de folosit. În aceste cazuri apar probleme de securitate, probleme de memorie, probleme de mentenanță și dezvoltare ulterioară, etc.
Programarea declarativă funcțională
Programarea funcțională se referă la stilul și limbajele de programare în care computația se tratează evaluând expresii matematice. Spre deosebire de programarea imperative, unde apar stări și variabile, programarea funcțională pe bazează pe un sistem formal numit lambda-calcul, care descrie un program sub forma compunerii unor funcții matematice.
Unul din primele limbaje funcționale este Lisp dar există și limbaje funcționale moderne (Scala, Haskel, etc.). Ce e și mai interesant este faptul că limbajele imperative sau OOP consacrate (C++, Java) au început în ultimul timp să suporte și ele expresii lambda, fapt care duce treptat la apariția unor limbaje de programare hibride.
Programarea orientată obiect
Programarea orientată obiect are ca punct de plecare programarea procedurală, în sensul că se bazează tot pe noțiunile de stare și variabile, dar introduce o serie de concepte care ajută la structurarea programelor:
- clase și obiecte;
- încapsulare;
- polimorfism;
- moștenire.
Tipuri de date
Structura în C
Plecând de la limbajul C, ne amintim că acesta pune la dispoziție o serie de tipuri de date primitive, incluse în standardul limbajului. Ca exemple, avem: int, long, char, double, etc. În plus, există posibilitatea de a crea structuri compuse folosind cuvântul cheie struct. O structură în C este compusă din una sau mai multe variabile care pot fi ori de tip primitiv, ori alte structuri.
În continuare avem un exemplu de definiție a unor structuri în C.
struct string{
char* str;
unsigned length;
};
struct person{
struct string *first_name;
struct string *last_name;
unsigned age;
float height;
float weight;
};
Se vede că structura person conține pointeri la două structuri de tip string. Relația este descrisă de schema bloc următoare (cu exemple de valori pentru variabilele primitive):
În continuare, vom da un exemplu de utilizare a acestor structuri:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
//make a default string with no content and length = 30
struct string * some_string = (struct string*)malloc(sizeof(struct string));
unsigned default_length = 30;
some_string->length = default_length;
some_string->str = (char*)malloc(default_length * sizeof(char));
strcpy(some_string->str, "Vasile");
//make a person structure in which all strings refer to the default empty string
struct person* new_person = (struct person*)malloc(sizeof(struct person));
new_person->first_name = some_string;
new_person->last_name = some_string;
new_person->age = 29;
new_person->height = (float)1.7;
new_person->weight = 68.9F;
printf("Persoana se numeste %s %s, are varsta de %d ani, inaltimea %f si greutatea %f\n", new_person->first_name->str,
new_person->last_name->str,
new_person->age,
new_person->height,
new_person->weight);
return 0;
}
În acest exemplu, schema bloc este diferită dintr-un punct de vedere esențial: ambii pointeri de tip string sunt referință la aceeași adresă, respectiv la același string. Astfel, dacă se modifică new_person->first_name, atunci implicit se modifică și new_person->last_name (de fapt este aceeași structură):
Pentru a face un rezumat, structura, in C, este un tip de dată compusă din tipuri primitive, sau alte structuri. Analog cu orice alt tip de dată, se pot defini variabile de tipul structurii, așa cum se pot defini variabile de tip primitiv. Limitarea fundamentală a structurilor este că acestea nu pot conține decât date, nu și funcții. Astfel se introduce noțiunea de clasă.
Clasa și obiectul