Documente Academic
Documente Profesional
Documente Cultură
PE OBIECTE
CONCEPTE GENERALE
Stilul de programare care îl numim în mod obişnuit
programare orientată pe obiecte POO a apărut relativ recent
în istoria limbajelor de programare.
Acesta este un stil particular şi foarte comod pentru
numeroase situaţii.
El a fost creat pentru a depăşii limitele programării
structurate bazate în principal pe utilizarea largă a
procedurilor, funcţiilor, a pointerilor sau a tipurilor de date
mai mult sau mai puţin evoluate.
Programarea structurată foarte practică mai ales pentru
sisteme de programe mici sau aplicaţii reduse negrafice, este
depăşită în ceea ce priveşte aplicaţiile mari cu elemente
grafice unde mult mai indicată este programarea orientată pe
obiecte.
Programarea orientată pe obiecte utilizează elementele
programării dar se bazează pe orientarea pe obiecte.
CONCEPTE GENERALE
Orientarea pe obiecte reprezintă organizarea de resurse soft
într-o colecţie de obiecte, distincte şi discrete, care înglobează
atât structuri de date cât şi funcţiile de prelucrare ale acestora.
Această organizare este o extindere a programării tradiţionale,
în care structurile de date şi funcţiile de prelucrare sunt doar
lejer conectate.
Identificarea obiectelor pentru o aplicaţie dată se face prin
maparea conceptelor de bază vehiculate de aplicaţia
respectivă.
Un obiect se defineşte ca fiind un concept, o abstractizare şi
înţeles precis din punct de vedere al aplicaţiei de rezolvat.
Obiectele permit următoarele avantaje:
oferă o mai bună înţelegere a problemei de rezolvat;
oferă un "schelet" de pornire pentru implementare.
O clasă de obiecte grupează un număr oarecare de obiecte cu
proprietăţi similare. Această similitudine se referă atât la
descriere (date sau atribute), cât şi la comportare (funcţii sau
metode), dar în acelaşi timp şi la relaţiile posibile cu alte
obiecte.
CONCEPTE GENERALE
Diferenţele dintre obiectele de aceeaşi clasă se materializează în
diferenţe între valorile datelor de descriere.
Totodată, pentru fiecare obiect este specificat tipul clasei din
care provine. Clasa este elementul de programare care ne
permite transcrierea cât mai bună a unui concept din viaţa
concretă într-un limbaj de programare. Ea permite definirea atât a
datelor relativ la o entitate cât şi a acţiunilor asociate (funcţii sau
metode).
Implementare software a unui concept cum ar fi un sistem de
calcul se poate printr-o clasă. Această clasă va fi caracterizată de
anumite date (atribute) şi anumite acţiuni (metode, funcţii).
Această clasă va conţine numai elementele caracteristice, putând
definii pe baza ei şi concepte particulare cum ar fi laptop şi PDA.
Reprezentarea acestor clase este dată în figura 1.
Atributele reprezintă caracteristici unice în cadrul unei clase de
obiecte. La nivel de obiect fiecare atribut primeşte o anumită
valoare care se poate modifica pe parcursul duratei de viaţă a
obiectului respectiv. Două sau mai multe obiecte pot avea valori
identice sau valori diferite pentru un acelaşi atribut.
CONCEPTE GENERALE
CONCEPTE GENERALE
Metodele sau operaţiile sunt funcţii de prelucrare care se aplică
obiectelor de o anumită clasă. Toate obiectele unei clase admit
acelaşi set de metode, metode care la rândul lor pot să
primească un număr oarecare de parametri suplimentari.
Identificarea unei metode se face atât prin nume, cât şi prin
semnătură.
Pentru ca unui obiect să i se poată aplica metode - funcţii de
prelucrare - acel obiect trebuie să fie creat (definit). Definirea
unui obiect poartă numele de instanţiere. După ce un obiect şi-a
îndeplinit misiunea el este eliminat. Durata de viaţă a obiectelor
depinde de la obiect la obiect şi de la aplicaţie la aplicaţie.
Abstractizare şi modelare
In orice domeniu de activitate umană, abordarea unui proiect porneşte
de la construirea unui model cu scopul unei mai bune înţelegeri a
problemei de rezolvat.
Prin abstractizare se izolează aspectele esenţiale de cele neesenţiale,
bineînţeles în funcţie de perspectiva de abordare a problemei de
rezolvat.
În consecinţă, pentru o aceeaşi problemă, pot exista mai multe
abstractizări, deci mai multe modele. Nu putem vorbi de modele corecte
şi modele incorecte, ci de modele adecvate şi modele inadecvate.
Prin esenţă, o abstractizare este o reprezentare incompletă a realităţii şi
tocmai aceasta dă valoare modelului corespunzător.
La fel ca şi în abordarea structurată, în abordarea orientată pe obiecte,
procesul dezvoltării unei resurse soft, porneşte de la un model.
Aceasta este o abstractizare menită a face posibilă etapa următoare de
implementare. În domeniul ingineriei soft, programarea structurată a
făcut un mare pas înainte introducând necesitatea abordării unei
aplicaţii din trei perspective diferite, rezultând astfel trei modele diferite.
În abordare structurată, cele trei modele, pe care le numim şi sub-
modele sunt:
modelul static;
modelul dinamic;
modelul funcţional.
Abstractizare şi modelare
În modelarea orientată pe obiecte apar două modificări esenţiale:
modelul care captează aspectele statice ale aplicaţiei devine
modelul obiectual
accentul cade pe acest model şi nu pe cel funcţional.
În multe aplicaţii mai simple modelele dinamic şi funcţional se
construiesc în primul rând pentru o mai bună înţelegere a
modelului obiectual.
Modelul obiectual
Pune în evidenţă aspectele statice ale aplicaţiei, dar nu prin
identificarea unor sub-ansamble, mai mult sau mai puţin arbitrare,
ci prin identificarea conceptelor cu care operează aplicaţia.
Acestor concepte li se asociază obiecte, iar modelul obiectual
conţine o sinteză a acestor obiecte, a relaţiilor dintre ele, precum
şi a proprietăţilor lor.
Construirea unui sistem în jurul obiectelor cu care operează,
surprinde mult mai bine realitatea decât o abordare care porneşte
de Ia aspecte funcţionale.
Abstractizare şi modelare
Modelul dinamic
Sugerează succesiunea în timp a creării obiectelor, pe măsura
necesităţii existenţei lor, precum şi distrugerea acestora după ce şi-au
îndeplinit misiunea.
Crearea unui obiect mai poartă şi numele de instanţiere.
Pentru obiectele implementate Ia nivelul unui nucleu, deciziile de
instanţiere şi distrugere se iau la nivelul clientului acelui nucleu.
Totodată, modelul dinamic indică ordinea de invocare a a metodelor,
pentru fiecare obiect instanţiat.
Modelul funcţional
Descrie aspectele comportamentale ale obiectelor, indiferent de
ordinea de instanţiere a obiectelor şi indiferent de ordinea de invocare a
acestor aspecte.
Fiecărui aspect comportamental îi corespunde o funcţie, numită şi
metodă. Modelul funcţional, descrie funcţionarea în mare a acestor
metode, rezumându-se la ilustrarea relaţiilor între parametrii de intrare
şi valorile de ieşire ale fiecărei metode în parte, fără însă a oferi detalii
legate de implementarea algoritmilor corespunzători.
Metodologii orientate pe
obiecte
Există la ora actuală mai multe metodologii orientate pe obiecte pentru
analiza, proiectarea şi implementarea de resurse soft.
Una din metodologii este OMT - Object Modeling Technique .
Aceasta presupune o etapizare a etapelor de dezvoltare, precum şi un
sistem grafic de reprezentare a obiectelor şi a relaţiilor dintre acestea.
Metodologia OMT se bazează pe construirea unui model tridimensional
al aplicaţiei, pe baza căruia se adaugă gradat detaliile de implementare
în ultima fază a procesului de dezvoltare.
În mare, metodologia OMT este ilustrată în figura 2.
class A {
static int i;
};
int A::i;
main()
{
A::i=10;
A od;
int n = od.i;
}
Cuvântul cheie this
La apelarea unei funcţii membre, aceasta este informată asupra identităţii
obiectului asupra căruia va acţiona prin transferul unui parametru implicit
care este adresa obiectului.
De exemplu, în cazul apelului:
ob.verificare(i); funcţia verificare() primeşte şi adresa obiectului ob, în afară
de valoarea i.
De asemenea există cazuri în care adresa obiectului este necesar să fie
utilizată în definiţia funcţiei.
Acest lucru este realizat în C++ de cuvântul cheie this, asociat unui pointer
către obiectul pentru care s-a apelat funcţia.
Cuvântul this are sens şi poate apare numai în definiţia unor funcţii
membre.
Exemplul următor adaugă clasei student o funcţie adresa(), care afişează
adresa obiectului:
Exemplul 1:
student::adresa()
{
cout<<”Adresa obiectului pentru care s-a apelat funtcia este”;
cout<<this;
}
Cuvântul cheie this
............
student stTI; // Se defineşte un obiect stTI aparţinând clasei TI.
stTI.adresa(); // Afişează adresa obiectului stTI.
Exemplul 2
Vom crea două obiecte de tip numărător n1 şi n2. Utilizând pointerii *n1
şi *n2 putem reprezenta grafic modul în care pointează aceste obiecte.
void main( )
{
using namespace std;
int i = 10;
cout << i << endl;
cout.unsetf( ios_base::dec );
cout.setf( ios_base::hex );
cout << i << endl;
cout.setf( ios_base::dec );
cout << i << endl;
cout.setf( ios_base::hex, ios_base::dec );
cout << i << endl;
}
UTILIZAREA FUNCŢIILOR WIDTH()
ŞI PRECISION()
Există trei funcţii membre ale clasei IOS, care poziţionează
parametrii de format:
lăţimea câmpului
precizia
void main( ) {
cout.width( 20 );
cout << cout.width( ) << endl;
cout << cout.width( ) << endl;
}
UTILIZAREA FUNCŢIILOR WIDTH()
ŞI PRECISION()
Exemplu:
#include <iostream>
int main( )
{
using namespace std;
float i = 31.31234F;
cout.precision( 3 );
cout << i << endl; // afiseaza 3 digiti semnificativi
cout << fixed << i << endl; // afiseaza trei digiti dupa punct
}
Supraîncărcarea operatorilor << şi >>
Până acum s-a prezentat supraîncărcarea unor operatori în relaţie cu
anumite clase.
Atunci când dorim sa afişăm datele unei clase, utilizarea lui cout şi a
operatorului de extragere << poate conduce la necesitatea scrierii unui
număr important de linii de program.
Acelaşi lucru este valabil şi în situaţia în care dorim să introducem
datele unei clase prin utilizarea lui cin şi a operatorului de înserare >>.
O alternativă la această problemă ar fi supraîncărcarea operatorilor de
înserare şi de extragere.
Aceasta supraîncărcare permite să se realizeze o citire sau o scriere
cu anumite formatări sau în anumite configuraţii.
Pentru streamul cout avem următoare secvenţă generală de
supraîncarcare a operatorului de inserare:
ostream& operator <<(ostream &flux_atasat, tip_clasa obiect)
{
// corpul funcţiei de înserare
return flux_atasat;
}
Supraîncărcarea operatorilor << şi >>
Funcţia returnează o referinţă de tipul ostream – o clasă pe care C++ o
derivează din clasa IOS şi care acceptă ieşirea. Primul parametru al
operatorului este fluxul în care se va însera, iar al doilea este obiectul
care va fi afişat în flux.
Dacă operatorul << este supraîncărcat el poate fi utilizat astfel:
tip_ clasa a,b,c;
cout<<a<<b<<c;
Funcţiile de înserare vor face aproximativ aceiaşi paşi pe care îi fac de
obicei, numai că îi vor face prin fluxul obiect şi nu direct prin cout, cerr
sau clog.
Pentru supraîncărcarea operatorului de extragere >> care operează cu
streamul cin se va folosi structura:
istream& operator>>(istream &flux_atasat, tip_clasa obiect)
{
// corpul funcţiei de extragere
//se va lucra asupra streamului de intrare
//se vor face formatarile streamului si va citi efectiv prin stream
//se va returna obligatoriu fluxul atasat
return flux_atasat;
}
Supraîncărcarea operatorilor << şi >>
Se observă că spre deosebire de funcţiile supraîncărcate, trebuie să
se transmită o referinţă spre obiectul din cadrul funcţiei de extragere
supraîncărcate.
Funcţiile de extragere returnează o referinţă la un flux de tipul istream,
care este derivat din clasa flux de intrare IOS.
Primul parametru este o referinţă la un flux (în general cin).
Fereastra ExempluPO
Efectuarea compilării şi a editării de legături
Procesul de asamblare efectuează compilarea fişierelor C++
individuale dintr-un proiect, după care rezultatele sunt legate
împreună pentru a forma fişierul executabil.
Pentru a asambla proiectul ExempluPO, se efectuează clic pe
butonul Build sau se selectează Build ExempluPO.exe din meniul
Build.
ExempluPO.exe se află în subdirectorul /Debug din directorul
/ExempluPO al proiectului.
Acest subdirector conţine, de asemenea, fişierele obiect ale
programelor din cadrul proiectului.
Subdirectorul /Debug a fost creat din cauză că s-a ales o
configuraţie pentru depanare, în timp ce o configuraţie pentru
versiunea finală ar fi plasat fişierele într-un subdirector numit
/Release.
Pagina Build a secţiunii Output înfăţişează informaţii privind
procesul de asamblare.
În cazul în care codul sursă conţine erori, acestea sunt afişate în
cadrul paginii Build, ilustrată în figura următoare. Deoarece
AppWizard a generat întreg codul, nu ar trebui să apară erori.
Efectuarea compilării şi a editării de legături
Executia proiectului ExempluPO –F5 sau Debug ->Start Debugging
Efectuarea compilării şi a editării de legături
Fereastra aplicaţiei conţine două butoane, OK şi Cancel, şi afişează un text.
Există, totodată, o bară de titlu care afişează o pictogramă asociată, numele
aplicaţiei şi un buton de închidere.
Bara de titlu conţine şi un meniu de sistem şi poate fi utilizată pentru a
deplasa fereastra pe ecran prin efectuarea unui clic asupra ei şi menţinerea
butonului mouse-ului apăsat.
Putem afişa informaţiile despre aplicaţie dacă se efectuează clic pe
imaginea MFC din colţul stânga sus al ferestrei ExempluPO şi se
selectează About ExempluPO din meniul de sistem care apare (figura
următoare).
Modificarea interfeţei aplicaţiei
Elementele vizuale ale unui proiect se numesc resurse.
Spre exemplu, casetele de dialog, pictogramele şi meniurile constituie
resurse.
Numit sugestiv editor de resurse, acesta este instrumentul din Visual
Studio care se foloseşte pentru proiectarea resurselor de diferite tipuri
şi modificarea aspectului efectiv al aplicaţiei.
Pentru a adăuga un nou buton, va trebui să se deschidă macheta
casetei de dialog.
Pentru aceasta se parcurg următorii paşi:
1. Se selectează pagina ResourceView a secţiunii spaţiului de lucru al
proiectului. Se va afişa lista cu resursele proiectului.
2, Se expandează lista de resurse prin efectuarea unui clic pe semnul +
din stânga etichetei ExempluPO Resources şi se expandează catalogul
Dialog. Aşa cum se vede în figura următoare, apar doi identificatori de
dialog, IDD_ABOUTBOX ŞI IDD_EXEMPLUPO_DIALOG.
Modificarea interfeţei aplicaţiei
3. Se efectuează un dublu clic pe identificatorul
IDD_EXEMPLUPO_DIALOG.
În consecinţă va fi afişată macheta ferestrei dialog principale a aplicaţiei
ExempluPO, ca în figura următoare.
Modificarea interfeţei aplicaţiei
La rularea programului, dialogul va apărea aşa cum apare în editorul
de resurse.
Acum se poate modifica macheta dialogului prin intermediul
editorului de resurse.
Pentru adăugarea unui buton în cadrul dialogului ExempluPO se
parcurg următorii paşi:
1. Înainte de a adăuga butonul, se înlătură controlul etichetă TODO
care apare în centul machetei dialogului ExempluPO.
Se efectuează un clic pe textul TODO: place dialog controls here; în
jurul textului este afişat un dreptunghi de formatare (figura
următoare).
Se apasă tasta Delete. Controlul etichetă este înlăturat de pe
macheta dialogului.
Modificarea interfeţei aplicaţiei
Ştergerea textului implicit din caseta de dialog
Modificarea interfeţei aplicaţiei
2. Se selectează controlul buton din caseta cu
controale.
Se deplasează mouse-ul deasupra machetei
dialogului.
Aflat pe suprafaţa machetei, cursorul mouse-ului
devine o cruce pentru a indica poziţia în care va fi
plasat noul buton.
Se plasează pointerul (crucea) departe de
butoanele OK şi Cancel şi apoi se efectuează un
clic cu mouse-ul. Astfel se va afişa un nou buton,
etichetat Buttonl, ilustrat în figura următoare.
Modificarea interfeţei aplicaţiei
Adăugarea unui buton în cadrul casetei de dialog
Modificarea interfeţei aplicaţiei
3. Pentru, a modifica eticheta butonului, trebuie ca acesta să fie selectat
(încadrat de un dreptunghi de formatare.
Dacă butonul nu este selectat, se selectează prin efectuarea unui clic pe
suprafaţa sa. Tastaţi Confirma. Odată ce tastaţi, este afişată caseta de
dialog Push Button Properties.
4. Se tastează IDC_CONFIRMA în cadrul casetei combinate ID din caseta
de dialog Push Button Properties, înlocuind textul implicit
IDC_BUTTON1. Astfel, identificatorul butonului are o semnificaţie mai
evidentă.