Programare Orientata Obiect Novac

Post on 29-Dec-2014

62 views 10 download

description

curs facultate anul II, profesor Novac-Ududec.

Transcript of Programare Orientata Obiect Novac

1

LIMBAJUL C++

Programarea orientată peobiecte

2

Introducere

Există limbaje concepute strict pe baza POO, ex. Simula, Smalltalk, Java;

O altă abordare - adaugarea tehnicilor POO limbajelor cu mare polularitate, ex. Pascal şi C;

C++ combină avantajele oferite de C (eficienţă, flexibilitate, portabilitate) cu avantajele oferite de POO.

3

Programarea orientată pe obiecte în C++

Scopul limbajului C++ este să permită dezvoltarea programelor complexe (peste 25.000 linii cod sursă);

C++ asigură programatorului libertatea şi controlul din C, împreună cu puterea obiectelor;

POO combină metodele programării structurate cu concepte noi;

4

C++ conţine îmbunătăţiri ale limbajului C care nu sunt direct legate de POO, cum ar fi: Tipul referinţă; Funcţii inline; Supraîncărcarea operatorilor; Operatori pentru gestionarea memoriei

libere.

5

Ce este programarea orientată pe obiecte ?

În POO se împarte o problemă în subgrupe de secţiuni înrudite, care ţin seamă atât de cod cât şi de datele corespunzătoare din fiecare grup.

Se organizează apoi, aceste subgrupe pe structuri ierarhice;

Se transformă subgrupele în unităţi de sine stătătoare, numite obiecte.

6

Toate limbajele OO au 3 caracteristici comune: încapsulare, polimorfism şi moştenire

Încapsularea este un mecanism care leagă împreună cod şi date;

Permite crearea unui obiect; Un obiect este o entitate logică care

încapsulează atât date cât şi cod care manevreză aceste date;

Când se defineşte un obiect, implicit se creează un nou tip de date !

7

Polimorfism

În POO polimorfismul se aplică metode-lor unei clase şi permite definirea unor funcţii cu acelaşi nume dar cu comportament diferit (specific);

Exemplu: metoda de calculat aria unui poligon;

8

Moştenirea

Este procesul prin care un obiect poate să preia prototipul altui obiect;

Se admite astfel conceptul de clasificare;

Exemplu: Clasa mamifer

Clasa pisica Clasa pisică birmaneză

9

Inregistrare - Clasă

În numeroase aplicaţii, este necesar să se prelucreze date grupate sub forma de înregistrări, situate fizic fie în fişiere, fie înmemoria internă.

Să considerăm, de exemplu, evidenţamaterialelor dintr-o magazie.

Fiecare material se caracterizează prin maimulte atribute, cum sunt: codul materialului, denumirea materialului, cantitatea.

10

Informaţia despre un material ar putea fi, deci, păstrată pe un formular de hârtieavând, ca exemplu, următorul conţinut:

MATERIAL Cod material: 13027522 Denumire material: Pânza albă bumbacCantitate: 127.53

11

Pentru prelucrare, aceste date sunt grupateîntr-o înregistrare de forma:

127.53Pânza albă bumbac13027522

12

Remarcăm că această structură, care se introduce în memoria calcula-torului, conţine numai datele, nu şi alteinformaţii, cum ar fi denumirile atribu-telor şi tipurile de date din fiecare câmp.

Descrierea acestei structuri se face înprogram, folosind o instrucţiune numitădeclaraţie de structură.

Forma declaraţiei depinde de sintaxalimbajului de programare utilizat.

13

In limbajul C, aceleaşi declaraţii se fac sub forma:

typedef struct{ int cod; char nume[30]; double cantitate} Material;

Material a, b, c;

14

Remarcăm că nici în Pascal, nici în C nu este predefinit un tip de date numitMaterial, dar limbajul pune la dispoziţia programatorului modalitateaprin care el poate să definească un astfel de tip.

15

Înregistrarea (engl: record) este o structură de date neomogenă cu următoarele caracteristici:

Componentele înregistrării, numite înmod uzual câmpuri (engl. fields), au fiecare propriul său nume;

Câmpurile înregistrării pot aparţine unortipuri de date diferite (de aceea spunemcă este o structură neomogenă);

În memorie câmpurile sunt aşezateconsecutiv (în linie), ocupând o zonă de memorie compactă.

16

Primele două caracteristici se referă la conceptul abstract de înregistrare, iarultima caracteristică se referă la modulde implementare.

Câmpurile de date dintr-o înregistare pot conţine nu numai date primitive, ci şistructuri de date.

În particular, orice câmp al unei înregis-trări poate fi el însuşi o înregistrare.

17

Clasa ca extindere a structuriide înregistrare În limbajele de programare OO, structura de

înregistrare a fost extinsă, astfel încât în afară de date sa conţină şi metode, adică funcţii sauproceduri prin care se prelucrează datele respective.

S-a obţinut astfel conceptul de clasă. Clasa nu mai este o simplă structură de date, ci un

modul de program, care conţine atât date, cât şimetode.

Se poate deci considera că înregistrarea este un cazparticular de clasă, care nu conţine metode.

18

Clasele – structuri abstracte de date, definite de utilizator, care “încapsulează” atât datele propriu-zise cât şi operaţiile efectuate asupra acestora.

Un obiect este o instanţă a unei clase. Clasa = abstractizare logică; Obiect = real, există în memoria

calculatorului; O clasă are atribute (caracteristici-date)

şi metode (funcţii);

19

Îmbunătăţiri ale limbajului C introduse în C++

1. Transmiterea parametrilorÎn C++ există 2 posibilităţi de transmitere a param. actuali către o funcţie: Prin valoare; Prin referinţă.

Primul este modul standard de transmitere a param. în C.

20

Transmiterea parametrilor prin referinţă

Prin folosirea param formali referinţă se permite realizarea transferului prin adresă, la fel ca în Pascal (paramerii VAR).

Se elimină astfel necesitatea utilizarii param formali pointeri, în cazul în care modificările făcute în interiorul funcţiei asupra param. trebuie să rămână şi după revenirea din procedură.

21

Exemplu

void schimbă(int &a, int &b){int aux=a; a=b; b=aux;} Transferul prin referinţă este util atunci

când programul are dimensiune mare (struct, class) şi crearea în stivă a unei copii a valorii lui reduce viteza de execuţie şi încarcă memoria.

22

2. Parametri cu valori implicite

În C++ se pot declara funcţii cu valori implicite ale parametrilor;

La apelarea acestor funcţii se poate omite specificarea param efectivi pentru aceia care au fost declaraţi cu valori implicite;

Este obligatoriu ca numai ultimii param să aibă valori implicite şi nu este permisă alternarea param cu şi fară valori implicite.

23

Exemplu- Val_impl.cpp

void fct(int, int=10);void fct(int p1, int p2){

cout<<p1; cout<<p2; }void main(){ fct(1,2);

fct(3);}

24

3. Funcţii inline

Prezenţa funcţiilor inline anunţă compila-torul să nu mai genereze cod maşină necesar apelului şi revenirii, ceea ce conduce la micşorarea duratei de execuţie.

Practic, funcţiile care au corpul format din maximum 3 instrucţiuni şi nu conţin instrucţiuni repetitive (for, while, do-while) pot fi declarate funcţii inline.

25

•Declararea funcţiei inline

inline <tip_vret><nume>(lista param. formali);

În cazul metodelor unei clase, dacă acestea sunt definite în interiorul clasei, ele sunt considerate implicit funcţii inline;

Există şi posibilitatea de a declara metoda la definirea clasei şi de a specifica, explicit, că este funcţie inline la definirea funcţiei.

26

Exempluclass Dreptunghi {//……….

public://….void seteaza_dim (double, double);

//declarare metoda};inline void Dreptunghi::seteaza_dim (double

L, double l){lung=L;lat=l;}

27

4. Supradefinirea (supraîncărcarea) funcţiilor

C++ permite supraîncărcarea (overloading) funcţiilor, adică existenţa mai multor funcţii cu acelaşi nume;

Compilatorul va determina care funcţie va fi apelată prin examinarea numărului şi tipului de argumente;

Nu se verifică şi tipul valorii returnate, deci 2 fct. supraîncărcate NU pot diferi doar prin valoarea returnată.

28

Exemplu

void fct(int a) {cout <<a<<”functia 1”;}void fct(char *a) {cout<<“\n”<<“a= “<<” functia 2”;}void main() {char a=‘A’;fct(3);fct(&a);}

29

5. Alocarea dinamică a memoriei folosind new şi delete

Operatorii new şi delete sunt similari fct. malloc() şi free(), dar constituie o metodă superioară adaptată POO;

Operatorul new poate fi folosit în următoarele situaţii:

int *ip1, *ip2,*ip3;ip1=new int; // var. intrega neinitializataip2=new(2); // var. int initializata cu 2ip3=new[100]; //tablou de 100 de intregi

30

Operatorii new şi delete

Operatorul new poate fi folosit şi la alocarea dinamică a obiectelor (apelarea constructorului clasei);

Operatorul delete este complementarul lui new şi permite eliberarea memoriei alocate (apelarea destructorului clasei).

31

6. Operatorul de rezoluţie

În C++ este definit un operator de rezoluţie ::, a cărui principală aplicaţie este legată de clase şi obiecte.

Exemplu:int n=1;void main() {int n=2; afiseaza(n); //afiseaza 2afiseaza(::n); // afiseaza 1}

CLASE ÎN C++

Tipul class

În C++ clasa este un concept fundamental prin care se definesc noi tipuri de date, prin asocierea unui set de funcţii la o structură de date;

Definirea unei clase presupune declararea ei prin specificarea numelui, lista claselor de bază din care este derivată clasa, dacă există, şi membrii clasei- atribute (date) şi metode (funcţii).

Definirea unei clase – antet şi corp Antetul este format din cuvântul cheie

class urmat de numele clasei. Corpul clasei este cuprins între {} şi

conţine membrii clasei, urmaţi de ; sau de o listă de declarare.

Exemplu: class Screen { /* ... */ };class Screen { /* ... */ } ecranA, ecranB;

Datele membre se declară exact ca variabilele C obişnuite, exceptând faptul cănu pot fi iniţializate explicit.

Exemplu

class Screen { short row, col; // nr linii şi coloanechar *cursor; // poziţia curentă a cursoruluichar *screen; // matricea ecran, row*col

};

Observaţii

Este bine ca datele membre să se specificeîn ordinea crescătoare a dimensiunii, acestfapt putând asigura o alocare optimă pe toatemaşinile.

Un obiect al unei clase poate fi declaratmembru doar dacă clasa a fost deja definită.

Definirea se încheie în momentul apariţiei }. Nu se pot declara membri de tipul clasei.

Declararea claselor

class nume_tip { modificator_control_acces:

lista_membrilor;} lista_variabile; Clasa reprezintă un tip de date definit de utilizator; Membrii unei clase sunt:- Atribute – datele declarate în cadrul clasei;- Metode – funcţii membre declarate sau definite în

clasă.

Modificator control accesclass <nume clasa>{private:

//zona privată- numai a clasei respective; de regulă cuvântul private poate lipsiprotected:

//zona (optională) accesibilă clasei şi descendenţilor ei;

public://interfaţa cu lumea exterioară clasei};

Exemplul 1: class dreptunghiclass dreptunghi {

double Lung, lat;public:void seteaza-dimen(double, double);double arata_Lung() {return Lung;}double arata_lat() {return lat;}double calcul_arie() {return Lung*lat;}

};

Membrii statici ai unei clase Fiecare obiect are propriile lui copii ale tuturor membrilor

acelei clase. Este posibila definirea de membrii care sa fie folositi în

comun de catre toate obiectele clasei. Datele statice exista într-o singura copie, comuna tuturor

obiectelor. Crearea, initializarea si accesul la aceste date statice

sunt total independente de obiectele clasei. Functiile membre statice efectueaza operatii care sunt

asociate întregii clase. Din acest motiv, la apelarea lornu este obligatorie indicarea unui obiect.

Exemplul 2:class masina{char *culoare;//membru implicit private

int capacit_cil; // membru private

public:void citire_date();int ret_capacit();

}; culoare si capacit_cil pot fi accesati numai

prin metodele clasei.

Exemplul 3

class Persoana{char *nume; // data privata

public:void citire_inf(); // metoda publica

private:int varsta; //data privata

};

Pointerul this

Fiecare funcţie membră are un argument ascuns numit this, transmis automat de către compilator.

Această variabilă (locală) reprezintă pointerul către obiectul curent (cel care apeleză metoda).

Să implementăm metoda calcul_ariefolosind acest pointer.

Exemplu pentru thisclass Dreptunghi{

double lung, lat;public:

//……………………void seteaza_dimen(double,double);

};void Dreptunghi::seteaza_dimen(double L, double

l){this->lung=L;this->lat=l;}

Obiecte Un obiect este o instanţă a unei clase;

Exemplu: dreptunghi a; Se pot declara oricate obiecte ale unei clase; Declararea obiectelor are o formă

asemănătoare declarării datelor de tip predefinit:

nume_clasa lista_obiecte;Exemplu: dreptunghi a,b,c;Dreptunghi.cpp

Domeniul unui numeVizibilitateTimp de viaţă

Domeniul unui nume Unui nume îi corepunde un domeniu,

specificat prin declaraţia variabilei; În funcţie de poziţia definirii unui nume,

domeniul poate fi: local (dacă numele este declarat într-un bloc; fişier (dacă numele este declarat în afara oricărui

bloc sau declaraţie de clasă); clasă;

Dacă un nume care are ca domeniu un fişier este redefinit într-un bloc inclus în domeniul său, el poate fi folosit în acel bloc dacă este precedat de operatorul de rezoluţie (::);

Exemplu#include <iostream.h>int i=89; // i declarat in afara oricarei func.,

// domeniul numelui este fisierulvoid main(){double i=99.9;cout<<“Valoarea lui i=“<<i<<‘\n’; // i=89cout<<“Valoarea lui i=“<<::i<<‘\n’; // i=99.9}

Domeniul numelui unui tip de date definit într-o clasă Se stabileşte în mod similar domeniului

oricărei variabile; Numele unui membru al unei clase are

un domeniu de tip clasă; Ca orice nume, un nume de clasă poate

fi redeclarat;

Exempluclass a {//………};//…..{ //instructiune bloc aflata in domeniul

numelui adouble a=99; //redeclararea lui aclass::a x; // x este un obiect de tipul a (al

clasei a)}

Vizibilitate

Domeniul de vizibilitate al unei variabile (obiect) este determinat de clasa de memorare a varibilei (obiectului)

De obicei domeniul de vizibilitate al unui nume coincide cu domeniul numelui.

Variabile locale şi variabile globaleDefiniţiiVaribilele declarate în afara oricărei funcţii

sunt variabile globale; Variabilele declarate în interiorul unui bloc

sunt variabile locale;Porţiunea de cod în care o variabilă este

accesibilă reprezintă scopul (domeniul de vizibilitate ) al variabilei respective;

Parametrii formali ai unei funcţii sunt variabile locale ale funcţiei respective;

Timpul de viaţă

Timpul de viaţă al unei variabile locale este durata de execuţie a blocului (funcţiei) în care a fost definită;

Timpul de viaţă al unei variabile globale este durata de execuţie a programului.

Exempluint x; //variabila globala, vizibila in tot

// programulvoid main(){ int a,b; // variabile locale main()//…….}int y; // variabila externa vizibila din acest

// punct si pana la sf. fisierului sursavoid func1(void){ int c,d; // variabile locale in func1//……..}

Clase de memorare Clasa de memorare determină timpul

de viaţă şi domeniul de vizibilitate al unei variabile

Se specifică la declararea variabilei, prin unul dintre cuvintele cheie:auto auto int a;register register char c;extern extern double z;static static int x;

Clasa de memorare auto Este clasa de memorare implicită

pentru o variabilă locală dacă nu se declară nimic;

Se alocă memorie automat la intrarea în blocul sau în funcţia în care este declarată.

Domeniul de vizibilitate este blocul sau funcţia unde a fost declarată;

Timpul de viaţă este durata de execuţie a blocului sau funcţiei respective.

Clasa de memorare register Variabilele din această clasă au aceeaşi

vizibilitate şi timp de viaţă ca şi cele din clasa auto;

Diferenţa constă în faptul că pentruvariabile register compilatorul utilizează regiştrii interni;

Unei variabile register nu i se poate aplica operatorul de referenţiere (::);

Clasa de memorare extern O varibilă globală are implicit clasa

extern, dacă nu există altă declaraţie; Domeniul de vizibilitate este din locul

declarării până la sfârşitul fişierului sursă;

Timpul de viaţă este durata execuţiei programului;

O variabilă din clasa extern este automat iniţializată la 0.

Clasa de memorare staticAre două utilizări distincte: Variabile locale statice – Dv = blocul

sau funcţia unde sunt definite; Tv=durata de execuţie a programului. Se iniţializează automat la 0.

Variabile globale statice – Dv = locul în care au fost definite şi până la sfârşitul fişierului; Tv = durata execuţiei programului.

1

CONSTRUCTORI ŞI DESTRUCTORI

2

În C++ se folosesc funcţii membre numite constructori şi destructori pentru crearea, iniţializarea, copierea şi distrugerea obiectelor. Constructorii şi destructorii sunt funcţii membre ale unei clase.

Un constructor – este o funcţie specială membră a unei clase şi are acelaşi nume cu acea clasă;

Are rolul de a iniţializa obiectele (instanţele acelei clase) atunci când sunt create.

3

Constructori şi destructoriconstr_destr.cpp Complementul constructorului este

destructorul- distruge obiectele create; Destructorul are acelaşi nume cu

constructorul, dar precedat de caracterul ~.

Obiectele locale sunt create când se intră în blocul lor şi distruse când se termină programul.

4

#include <iostream.h>int n_obiecte=0;class OB{public:

OB(){n_obiecte++;cout<<"Numarul obiectelor in viata

"<<n_obiecte<<endl;}~OB(){n_obiecte--;cout<<"Au mai ramas doar "<<n_obiecte<<" obiecte

"<<endl;}

};

5

void main(){OB a,b,c; //creez primele 3 obiecte{OB d,e;

} // aici distrug d si e{ // redeschid alt contextOB f; //crez un nou obiect f

} // distrug f} // eliberez memoria ocupata de obiectele a,b,c

6

Particularităţi specifice constructorilor Numele coincide cu numele clasei

căreia îi aparţine; În declaraţii nu se specifică nici un tip

de rezultat; Pot fi mai mulţi constructori pentru

aceeaşi clasă, deosebirea realizându-se prin mecanisme de overloading;

7

Particularităţi specifice constructorilor Pot avea parametri, inclusiv parametri

impliciţi; Un constructor nu poate fi apelatexplicit într-

un program, ci este apelat automat la crearea obiectului din clasa respectivă (static, auto, dinamic) inclusiv pentru obiecte temporare (în cazul alocării dinamice se foloseşte operatorul new);

8

Particularităţi specifice constructorilor

Nu se pot utiliza pointeri către constructori; Nu pot fi moşteniţi dar pot fi apelaţi de clasa

derivată; Dacă un constructor nu are parametri =

constructor cu lista vidă; Dacă o clasă nu dispune explicit de constructori

definiţi, complilatorul acţioneză automat un constructor ca funcţie membră publică, fiind în acelaşi timp constructor cu listă şi corp, ambelevide;

9

Particularităţi specifice constructorilor O clasă cu constructor private nu

poate avea obiecte. Ea poate fi doar baza unei ierarhii de clase.

10

Tipuri de constructori Există 3 tipuri de constructori care diferă prin

lista de aparametri:1. Constructor de copiere pentru construcţii de

forma adr1=ad2. Forma acestui constr. este<nume_clasa>(<nume_clasa>&);

2. Constructor cu listă şi corp vide, echivalent cu constructorul implicit;

3. Constructor de iniţializare. Nu are ca parametru un obiect deoarece se ocupă de iniţializarea obiectelor ce se vor construi. Nu trebuie să existe neaparat identitate între nr. de param. şi nr. de câmpuri. Se pot folosi şi parametri impliciţi.

11

Scopul folosirii constructorilor Asigură iniţializarea corectă a

obiectelor dintr-o clasă; Asigură unicitatea iniţializării; Au rolul construirii obiectelor, deci a

alocării memoriei; Sunt importanţi atât pentru obiecte

statice cât şi pentru obiecte din memoria dinamică.

12

Exemplu pentru cele 3 tipuri de constructori –Pers.cpp#include<conio.h>#include<iostream.h>#include<string.h>#define MAX 20class Adresa{char

nume[MAX],prenume[MAX],strada[MAX];int numar;

13

public:Adresa() {}; //constr. explicit cu lista si corp//Adresa(Adresa&); //constr. de copiereAdresa(char*, char*, char*, int);//contr.init.void tip_adresa();//metoda de afisare

};

14

Adresa::Adresa(char cnume[],char cprenume[], char cstrada[],int inumar)

{ strcpy(nume,cnume);strcpy(prenume,cprenume);strcpy(strada,cstrada);numar=inumar;

}void Adresa::tip_adresa(){ cout<<nume<<" "<<prenume<<"

"<<"str."<<strada<<" nr."<<numar<<'\n';}

15

void main(){ Adresa

adr1("Popescu","Ion","Domneasca", 21);Adresa adr2;

adr1.tip_adresa();adr2=adr1;adr2.tip_adresa();getch();}

16

Particularităţi specifice destructorilor Numele destructorilor este format din

caracterul ~ şi numele clasei căreia îi aparţine;

În declaraţii nu se specifică nici un tip de rezultat;

Nu are parametri şi nu poate fi supradefinit sau solicitat prin program pentru obiecte dinamice cu operatori anume, inclusiv pentru variabile temporale;

17

Particularităţi specifice destructorilor Nu se pot utiliza pointeri către

destructori; Nu pot fi moşteniţi dar pot fi apelaţi de

clasa derivată; Dacă o clasă nu dispune explicit de un

destructor, compilatorul generează un destructor implicit public cu corp vid;

18

Particularităţi specifice destructorilor Se apelează implicit pentru obiecte

alocate în memoria statică la sfârşitul execuţiei programului; - pentru obiectele de pe stivă-în momentul

ieşirii din blocul în care au fost definite; - pentru obiecte alocate dinamic cu new, la

apelarea dealocării cu delete.

19

Ordinea executării operaţiilor la apelarea constructorilor şi destructorilor1. Pentru constructori: - se alocă spaţiu îm memorie pentru

obiectul respectiv; - se execută instrucţiunile din

constructor, dacă există.

20

Ordinea executării operaţiilor la apelarea constructorilor şi destructorilor2. Pentru destructori: - se execută instrucţiunile din corpul

destructorilor, dacă există; - se distruge obiectul eliberând spaţiul de

memorie.Obsevaţie: Ordinea de apelare implicită pentru

destructorii unor obiecte este inversă ordinii în care au fost construite obiectele în blocul respectiv.

1

Clasa COMPLEX Să se definească tipul abstract de date

Complex care să aibă funcţii membru:ModulArgumentAccesul la partea realăAccesul la partea imaginarăAfişarea unui număr complex;şi constructori pentru iniţializare şi copiere.

2

Fişierul ClsCOMPLEX.hclass Complex {double real;double imag;public:Complex(double x=0,double y=0); //constructor de initializareComplex(const Complex&); //constructor de copiere

double modul(); //modulul nr complexdouble arg(); // argument nr complexdouble retreal(); // returneaza partea reala a nr. complexdouble retimag(); // returneaza partea imag a nr. complexvoid afiscomplex();void suma(Complex *,Complex *);

};

3

Fcmembre.cpp#include <math.h>#include <iostream.h>#define PI 3.14159#include "ClsCOMPLEX.h"//Constructor pentru initializareinline Complex::Complex(double x, double y){real=x;imag-y;

}// Constructor de copiereinline Complex::Complex(const Complex& z){real=z.real;imag=z.imag;

}// Calculeaza modulul nr complexinline double Complex::modul(){return sqrt(real*real+imag*imag);

}

4

// Calculeaza argumentuldouble Complex:: arg(){double a;if(real==0 && imag==0)a=0.0;if(real!=0 && imag!=0)a=atan(imag/real);if(real==0 && imag>0)a=PI/2;if(real==0&&imag<0)a=3*PI/2;

return a;}// Returneaza partea realainline double Complex::retreal(){ return real;}// Returneaza partea imaginarainline double Complex::retimag(){ return imag;}//Afiseaza numar complexinline void Complex::afiscomplex(){cout<<real<<"+"<<imag<<" i"<<'\n';}

5

Complexe.cpp- program care realizează următoarele: Citeşte perechi de numere care reprezintă

partea reală şi respectiv imaginară a unui număr complex;

Afişează: - Numărul complex citit; - Modulul fiecărui număr complex citit; - Suma numerelor complexe citite.

6

void main(){float re;float im;cout<<"Partea reala ";cin>>re;cout<<"Partea imaginara ";cin>>im;Complex z1(re,im),z2(5,8),z3;cout<<"Primul numar complex"<<'\n';z1.afiscomplex();cout<<"Modulul= "<<z1.modul()<<'\n';cout<<"Argumentul= "<<z1.arg()<<'\n';cout<<"Al doilea numar complex"<<'\n';z2.afiscomplex();z3.suma(&z1,&z2);cout<<"Suma numerelor complexe este "<<'\n';z3.afiscomplex();}

7

Funcţii friend

Se poate permite unei funcţii care nu este membră să aibă acces la membrii private şi protected ai clasei căreia îi este prietenă (friend).

Pentru a declara o funcţie friend se include prototipul ei în acea clasă, precedat de cuvântul cheie friend.

8

Spre deosebire de funcţiile membre funcţiile friend nu posedă pointerul this implicit.

Acest lucru conduce la faptul că o funcţie friend are un parametru în plus faţă de o funcţie membru care are acelaşi efect.

O funcţie poate fi în acelaşi timp funcţie membră a unei clase şi prietenă a altei clase.

9

Exempluclass CLS1 {int f1(int, char); // f1 metoda a clasei CLS1//…

};class CLS2 {friend int CLS1::f1(int, char); // f1 – friend

// clasa CLS2};

10

În cazul în care se doreşte ca toatefuncţiile membre ale unei clase să aibăacces la membrii privaţi ai altei clase (să fie funcţii prietene), prima clasă poate fi declarată clasă prietenă pentru cea de-a doua.

11

Exempluclass CLS1;class CLS2 { //….friend CLS1; // CLS1 este clasa prietena

CLS2// …

};

12

Relaţia de clasă prietenă nu estetranzitivă.

Astfel, dacă clasa CLS1 este clasă prietenă a clasei CLS2, iar clasa CLS2 este clasă prietenă clasei CLS3, aceasta NU implică faptul că CLS1 este clasă prietenă pentru CLS3.

13

Modificatorii de protecţie nu au nici o influenţă asupra unei funcţii prietene;

De aceea, specificarea faptului că o funcţie este prieten pentru o clasă poate fi scrisă în orice punct din interiorul definiţiei clasei respective.

Funcţia prieten nu este protejată şi deci poate fi utilizată fără nici o restricţie, ca o funcţie obişnuită.

14

Să se scrie o funcţie care ridică un număr complex la o putere întreagă pozitivă.

Formula lui Moivre:(r*(cos(a)+isin(a)))**n=r**n(cos(n*a)+isin(n*a)unde:a=argumentul numarului complex;r=modulul nr. complex.

15

Funcţia cputerevoid cputere(Complex& z,int n){ double r,a;r=z.modul();a=z.arg();double rlan=pow(r,(double)n);double na=n*a;z.real=rlan*cos(na);z.imag=rlan*sin(na);}

16

Observaţie

Funcţia cputere nu este o funcţie membră a clasei Complex;

Ea are acces la atributele real şi imag ale obiectului de tip complex referit de z, numai dacă este o funcţie prietenă a clasei Complex.

1

Moştenirea-ierarhii de clase în C++

2

Mecanismul moştenirii

Caracteristică a limbajelor POO, care permite refolosirea şi extinderea funcţionalităţii claselor existente;

Permite crearea unei ierarhii de clase şi trecerea de la clase generale la clase particulare;

Procesul implică la început definirea clasei de bază, care stabileşte proprietăţile comune.

3

Moştenirea poate fi:

Unică- o clasa are doar o superclasă, rezultând o structură arborescentă;

Multiplă – o clasă are mai multe superclase, rezultând o structură de reţea.

Înformaţia comună apare în clasa de bază, iar informaţia specifică, în clasa derivată.

4

5

Clasa derivată reprezintă o specializare a clasei de bază;

Orice clasă derivată moşteneşte datele membre şi metodele clasei de bază;

Acestea nu trebuie redeclarate în clasa derivată.

6

Nivelul de acces la membrii unei clase private – membrii (date şi metode) pot

fi accesaţi doar prin metodele clasei; protected – membrii pot fi accesaţi prin

funcţiile membre ale clasei şi funcţiile membre ale clasei derivate;

public – membrii pot fi accesaţi din orice punct al domeniului de existenţă al clasei respective;

friend – membrii pot fi accesaţi prin funcţiile membre ale funcţiei prietene specificate.

7

Tipul de moştenire Publică – în clasa derivată, nivelul de acces

al membrilor este acelaşi ca în clasa de bază. Privată – membrii protected şi public din

clasa de bază devin private în clasa derivată. Protejată (compilatoare mai noi)– la fel ca în

moştenirea privată, dar membrii publici ai clasei de bază devin protejaţi în timpul derivărilor ulterioare.

8

9

Clase derivate

O clasă derivată include toate caracteristicile clasei de bază şi în plus atribute proprii;

La declarare se specifică o listă a claselor de bază, precedate de modificatorul de acces care precizează tipul moştenirii.

10

Forma generală a moştenirii

class <nume_clasa_deriv>:<acces> <clasa_baza>{// corpul noii clase};<acces>:private, protected, public Obsevaţii:

O clasă derivată are acces atât la proprii membri cât şi la membrii publici ai clasei de bază.

11

Exemplu:

class Cladire{ //clasa derivata din cladireint camere, etaje, supraf; class Casa : public Cladire {public: int dormitoare, bai;void nr_camere (int num); public :int cate_camere(); void nr_dormitoare(int num); void nr_etaje (int num); int cate_dormitoare ();int cate_etaje (); void nr_bai (int num);void nr_supraf (int num); int cate_bai ();int cate_supraf(); };

};

12

Declararea clasei derivate Angajat, clasa de bază Persoana (moştenire simplă)

class Persoana{// corpul clasei

};class Angajat:protected Persoana{double salariu;

};

13

Declararea clasei derivate Interfaţa, cu clasele de baza Fereastra şi MeniuMoştenire multiplă

class Fereastra {// membrii clasei};class Meniu {//membrii clasei};class Interfata:public Fereastra, public Meniu{//membrii clasei};

14

Compilarea şi editarea de legături

Clasa derivată şi clasa de bază pot fi declarate în acelaşi fişier sursă sau în fişiere diferite.

15

Constructorii claselor derivate

Constructorii şi destructorii sunt funcţii membre care nu se moştenesc.

La instanţierea unui obiect din clasa derivată se apelează mai întâi constructorii claselor de bază, în ordinea în care aceştia apar în lista din declararea clasei derivate.

16

La distrugerea obiectelor, se apelează prima dată destructorul clasei derivate, apoi destructorii claselor de bază.

Transmiterea argumentelor unei funcţii constructor din clasa de bază se face folosind o formă extinsă a declaraţiei constructo-rului clasei derivate, care transmite argumentul unuia sau mai multor constructori din clasa de bază.

17

Concluzii

În general, clasele utilizează constructori definiţi de programator;

Dacă aceştia lipsesc, compilatorul generează automat un constructor implicit pentru clasa respectivă;

18

La instanţierea unui obiect o parte din valorile primite ca parametrifolosesc la iniţializarea datelor membre ale clasei de bază, iar restul iniţializează datele clasei derivate.

1

Relaţia dintre constructorii şi destructorii claselor de bază şi ai clasei derivate

Moştenire în C++

2

Constructorii şi destructorii sunt funcţii membru care nu se moştenesc;La instanţierea unui obiect al unei

clase derivate se apelează atât constructorii clasei derivate cât şi cei ai claselor de bază;La început, se apeleză constructorii

claselor de bază şi apoi construc-torul clasei derivate;

3

Ordinea de apel a constructorilor corespunde cu ordinea în care sunt indicate clasele respective în lista_claselor_de bază din definiţia clasei derivate;

La distrugerea unui obiect al clasei derivate, destructorii se apeleză în ordinea inversă;

Deci, întâi se apeleză destructorul clasei derivate şi apoi se apleleză destructorii claselor de bază în ordinea inversă faţă de ordinea de apel a constructorilor la instanţierea obiectului respectiv;

4

La instanţierea unui obiect se trans-mit valori parametrilor constructo-rilor pentru iniţializarea datelor membru; În cazul unui obiect al unei clase

derivate, o parte din valori se folosesc pentru iniţializarea datelor membru specifice ale clasei deriva-te, iar restul pentru iniţializarea datelor membru ale claselor de bază;

5

Constructorul clasei derivate conţi-ne parametri pentru toate valorile care se utilizează la iniţializarea obiectelor;Transferul valorilor de iniţializare

pentru datele membru ale claselor de bază se defineşte cu ajutorul antetului constructorului clasei derivate;

6

Fie A o clasă derivată din clasele de bază B1, B2,...,Bn:

class A:public B1,public B2,...,public Bn{…

A(…); // prototip pentru constructor…};

Constructorul A are un antet de forma:A::A(…):B1(…),B2(…),…,Bn(…)

7

Constructorul A are o listă de parametri completă, adică pentru iniţializarea tuturor datelor membru ale unui obiect de tip A;

Expresia Bi(...) (i=1,2,..,n) din antetulconstructorului A conţine, în paranteză, o listă de expresii care definesc valori iniţiale pentru datele membru ale clasei Bi.

Dacă o clasă Bi nu are constructor, atunci pentru clasa respectivă nu va fi prezentă o expresie de forma Bi(...) în antetul constructorului A.

8

De asemenea, expresia respectivă nu va fi prezentă în antetul lui A dacă datele membru ale clasei Bi se iniţializează cu valori implicite sau clasa Bi nu are date membru;

Expresia Bi(...) este un apel explicit al uni constructor al clasei Bi.

Ordinea în care se scriu expresiile Bi(...) în antetul constructorului A este arbitrară;

Constructorii se apeleză întotdeauna în ordinea în care sunt scrise clasele în lista_claselor_de_bază.

9

O condiţie esenţială pentru a se putea apela constructorii claselor de bază prin intermediul clasei derivate este ca aceştia să aibă protecţia de tip protected sau public.Lista care defineşte apelurile

constructorilor claselor de bază nu este prezentă în prototipurile constructorilor claselor derivate ci numai în antetele acestora.

10

În general, clasele au constructori definiţi de programatori;Totuşi există situaţii în care o clasă

nu are constructori definiţi; În acest caz, complilatorul

generează în mod automat un constructor implicit (fară parametri) pentru clasa respectivă.

11

Exemple1. Clasa A este o clasă derivată din

clasa de bază B. Nici una din clase nu are un constructor,Fie instanţierea:A a;Obiectul a se instanţiază fară a se face iniţializări. La instanţiere se aplică constructorii impliciţi ai claselor, generaţi de compilator.

12

Exemplul 2

Clasa A este o clasă derivată a clasei de bază B;Clasa B are constructor cu toţi

parametri impliciţi:class B {

protected:double x,y;

13

public:B(double p=0,double q=0){x=p;y=q;

}…

}; Clasa A nu are constructor:

14

class A:public B{protected:

Boolean ecran;public:

interior();…

};Fie declaraţia:

A a;

15

Obiectul a se instanţiază apelându-se constructorul cu parametri impliciţi al clasei B.Datele membru x şi z se iniţializea-

ză cu valoarea 0, iar data membru ecran nu este iniţializată.

16

Exemplul 3Clasa A este o clasă derivată a

clasei B. Clasa B nu are constructor definit.class B {protected:

double x,y;public:…. // nu exista constructori

};

17

Clasa A nu are constructor:class A:public B {

protected :Boolean ecran;int abs,ord;

public:A(double p=0,double q=0,int lx=639,int ly=349)

{ // initializeaza datele membru ale clasei de baza

x=p; y=q;

18

// initializeaza datele membru specificeabs=lx;ord=ly;if(0<=p && p<=lx && 0<=q && q<=ly)

ecran=true;else

ecran=false;}

…};

19

Exemple de instanţieri

A a; /* a.x=0, a.y=0, a.abs=639, a.ord=349, a.ecran=true */

A b(100,400); /* b.x=100, b.y=400,b.abs=639, b.ord=349, b.ecran=false */

20

Exemplul 4 Clasa A este o clasă derivată a clasei B

şi ambele clase au constructori definiţi.class B {

protected:double x,y;

public:B(double xx=0,double yy=0){ x=xx; y=yy;}

…};

21

class A:public B {protected:

Boolean ecran;int abs,ord;

public:A(double p=0,double q=0,int lx=639, int ly=349):B(p,q){

abs=lx;ord=ly;

22

if(0<=p && p<=lx && 0<=q && q<=ly)ecran=true;

elseecran=false;

}…

};Se pot utiliza aceleaşi instanţieri ca

în exemplul 3.Se realizează aceleaşi instanţieri ca

în exemplul 3.

23

Observaţie:Datele abs şi ord pot fi instanţiate chiar în antetul constructorului ca mai jos:

A(double p=0,double q=0, int lx=639,int ly=349):B(p,q),abs(lx),ord(ly)

{if(0<=p && p<=lx && 0<=q &&q<=ly)

ecran=true;else

ecran=false;}…};

24

Observaţii O clasă derivată este necesar să aibă cel puţin

un constructor în cazul în care cel puţin o clasă de bază are un constructor care nu este implicit sau nu are toţi parametrii impliciţi;

Exemplele 1- 4 au fost analizate avându-se în vedere constructori obişnuiţi (nu de copiere !).

În lipsa constructorilor de copiere, compila-torul generează în mod automat constructori impliciţi, care, copiază datele membru ale obiectului sursă în datele membru ale obiectului destinaţie.

O copiere de acest tip se numeşte copiere bit cu bit.

25

Constructorii de copiere sunt necesari mai ales în cazul în care clasele au ca date membru pointeri spre zonele alocate dinamic în memoria heap;De asemenea, în condiţiile moşteni-

rii unor date membru ale claselor de bază, pot apărea situaţii în care copierea bit cu bit ar genera erori.

Supraîncărcarea operatorilor

SupraSupraîîncărcarea ncărcarea operatorilor operatorilor

îîn Cn C++++

2

• În C++ tipurile abstracte de date sedefinesc cu ajutorul claselor, dar nu se comportă la fel ca tipurile predefinite;

• Totuşi, există o serie de asemănări:– Datele de tip abstract (obiectele) se declară la

fel ca cele de tip predefinit;– De asemenea, ele pot fi iniţializate la

declarare.• În cazul tipurilor abstracte, operaţiile se

definesc cu ajutorul funcţiilor membre şi funcţiilor friend.

3

Exemplu

• Pentru clasa COMPLEX se pot definifuncţii membru şi funcţii friend pentru a realiza cele 4 operaţii aritmetice asupra obiectelor de tip COMPLEX.

• În definiţia de clasă de mai jos se foloseşte o funcţie membru şi una friend pentru adunarea, respectiv scăderea obiectelor de tip COMPLEX.

4

class COMPLEX {double real,imag;

public:COMPLEX(double x=0,double y=0) //constructor de

initializare{

real=x;imag=y;

}//functie membru pentru adunarea obiectelor de tip complex

COMPLEX adcomplex(COMPLEX& z2);//Functie friend pentru scaderefriend COMPLEX sccomplex(COMPLEX&, COMPLEX& );...

};

5

• În continuare se pot defini funcţiile adcomplex şi sccomplex ca mai jos:

COMPLEX COMPLEX::adcomplex(COMPLEX& z)//returneaza suma dintre obiectul curent// si cel transmis prin parametrul z{COMPLEX ztemp;ztemp.real=real+z.real;ztemp.imag=imag+z.imag;return ztemp;}

6

COMPLEX sccomplex(COMPLEX& z1,COMPLEX& z2)//returneaza diferenta z1-z2{

COMPLEX ztemp;ztemp.real=z1.real-z2.real;ztemp.imag=z1.imag-z2.imag;return ztemp;

}• Dacă a,b,c sunt 3 obiecte de tip Complex instanţiate

cu ajutorul declaraţiei:Complex a,b,c;

atunci instrucţiunea c=a.adcomplex(b);atribuie lui c de tip Complex rezultatul sumeiobiectelor complexe a şi b.

7

• De menţionat că apelul a.adcomplex(b) returnează un obiect de tip Complex la fel cum o funcţie de antet

tip nume_f(...)unde tip este un tip predefinit diferit de void

returnează o valoare de tip tip.În general dacă ob1 şi ob2 sunt obiecte din clasa CLASA:

CLASA ob1,ob2;atunci o expresie de forma ob1=ob2 esteadmisă de complilator şi ea atribuie lui ob1 valoarea obiectului ob2.

8

• Această atribuire se realizează prin copiere bit cu bit a valorilor componentelor lui ob2 în zonele de memorie alocate componentelor lui ob1.

• Cu toate acestea, tipul COMPLEX definit nu permite utilizarea operatorilor obişnuiţi pentru a exprima operaţii cu obiecte de tip COMPLEX ca în cazul operaţiilor cu numere de tip int, long, float sau double.

9

• Acest lucru este posibil prin mecamismul de supraîncărcare a operatorilor.

• Operatorii +şi – trebuie supraîncărcaţi pentru a realiza operaţii corespunzătoare cu obiecte de tip COMPLEX.

10

• Ca rezultat al supraîncărcării se ajunge ca operatorii respectivi să poată fi utilizaţi în expresii obişnuite cu operanzi obiecte de tipuri abstracte.

• Limbajul C++ permite supraîncărcarea numai a operatorilor existenţi în limbaj cu excepţia operatorilor:. :: ? :

11

• De asemenea, prin supraîncăr-care nu se poate schimba n-aritatea (unar sau binar), priori-tatea sau asociativitatea opera-torilor, acestea fiind elemente predefinite care se păstrează şi pentru tipurile abstracte.

12

• Supraîncărcarea operatorilor se realizează cu ajutorul unor funcţii membre sau prietene, speciale.

• Specificul lor constă în numele acestora.

• El se compune din cuvântul cheie operator şi unul sau mai multe caractere care definesc operatorul care se supraîncarcă.

13

Supraîncărcarea operatorului +pentru tipul COMPLEX

Complex Complex::operator +(Complex& z)//returneaza un obiect complex care este // sumadintre obiectul curent si cel //transmis prin z

{ Complex temp;temp.real=real+z.temp; temp.imag=imag+z.imag;return temp;}• În acest caz numele funcţiei este operator + , iar

în rest funcţia este identică cu funcţia membru adcomplex definită mai înainte.

14

• Efectul schimbării numelui din adcomplex în operator + este acela al supraîncărcării operatorului + pentru a admite ca operanzi obiecte de tip Complex.

• Deci, o expresie de forma a+b estelegală şi are ca rezultat un obiect de tip COMPLEX care reprezintă suma dintre a şi b.

15

• În locul expresiei a.adcomplex(b) care este mai puţin sugestivă vom utiliza :c=a+b;

• În mod analog putem supraîncărca operatorul – schimbând numele funcţiei fiend sccomplex cu operator –

• Se vor utiliza apoi expresii de forma a-b în locul apelului funcţiei sccomplex(a,b);

16

Supoper.cpp, Supoper1.cpp

Observaţii• Operatorii pot fi supraîncărcaţi prin funcţii

membre sau prin funcţii friend;• O diferenţa între cele două tipuri constă în

numărul de parametri;• Astfel funcţiile membru care supraîncarcă

operatori unari nu au parametri, iar cele care supraîncarcă operatori binari au un singur parametru;

• În cazul funcţiilor friend numărul parametrilor este egal cu n-aritatea operatorului care se supraîncarcă.

17

• La supraîncarcarea operatorilor pentru obiecte de tip abstract nu se face diferenţa între formele prefixate şi cele postfixate.

• În principiu, funcţiile membru care supraîncarcă un operator nu sunt statice cu excepţia operatorilor unari new şi delete care se supraîncarcă numai prin funcţii membru statice;

18

• Alţi operatori care prezintă particularităţi la supraîncărcare sunt parantezele, operatorul-> şi operatorul de atribuire =.

• Mai sus, am considerat supraîncărcarea operatorilor binari pentru cazul când ambii operanzi sunt de tip abstract COMPLEX;

• Se pune problema utilizării operatorilor respectivi şi cu operanzi diferiţi adică de forma:

• a+k, k+a, a-k, k-a unde:• k- variabilă de tip int, iar a obiect Complex.

19

• Există 2 soluţii pentru a utiliza expersii de această formă:

1. Supraîncărcarea operatorului + nu numai pentru operanzi de tip Complex, ci şi pentru operanzi diferiţi;

2. Conversia operandului care nu este de tip Complex într-un obiect de tip Complex, înainte de aplicarea operatorului. Acest lucru este destul de simplu dar nu întotdeauna eficient.

20

Soluţia 1• Pentru a legaliza expresii de forma:

a+k unde a este obiect Complex iar k o variabilă de tip int, putem adăuga o nouă funcţie operator membră sau friend de tipul:

Complex Complex::operator +(int k){ Complex ztemp;ztemp.real=real+k; ztemp.imag=imag;return ztemp;}Sau putem defini o funcţie friend cu acelaşi

efect:

21

Complex operator + (Complex& z1, intk)

{Complex ztemp;ztemp.real=real+k; ztemp.imag=imag;return ztemp;}

22

Adăugând una dintre aceste funcţii se pot utiliza instrucţiuni de forma :Complex a,b;int k;….b=a+k;b=a+123;

• Să observăm că funcţiile de mai sus implicăfaptul că primul operand este de tip Complexceea ce înseamnă că expresiile de formak+a 123+a

sunt ilegale.

23

• Pentru a accepta astfel de expresiieste necesar ca operatorul + să fie supraîncărcat în mod corespunzător, adică pentru expresii în care primul operand este de tip int şi al doilea este de tip Complex.

24

• O astfel de supraîncărcare se poate realiza dar numai printr-o funcţie friend deoarece în cazul funcţiilor membru, primul parametru este întotdeauna obiectul curent şi acesta nu poate fi de tip int.

• De aceea pentru a admite expresii în care primul operand este de tip int şi al doilea de tip Complex vom utiliza următoarea funcţie friend:

25

Complex operator + (int k, Complex z)// returneaza obiectul complex k+z{Complex ztemp;ztemp.real=z.real+k;ztemp.imag=z.imag;return ztemp;

}

26

• Din exemplu se vede că supraîncărcareaoperatorilor nu permite moştenireaproprietăţii de comutativitate a acestora;

• Astfel deşi operatorul + este comutativ pentru operanzi de tipuri predefinite, supraîncărcarea lui pentru expresii de forma a+k unde:- a este obiect de tip Complex- k este variabilă de tip int, nu este

valabilă pentru expresii de tip k+a.

1

FISIERE IN C++

2

Biblioteca standard a limbajului C++ oferă utilizatorului două ierarhii de clase pentru operaţii de I/E şi lucrul cu fişiere. Una are ca rădăcină clasa streambuf, iar cealaltă, clasa ios.

La bază se află conceptul de stream (flux). Prin stream se înţelege un flux de date de la sursă către o destinaţie sau consumator.

Clasa streambuf furnizează funcţii generale pentru lucru cu zonele tampon (bufere) şi permite tratarea operaţiilor de I/E fără a avea în vedere formatări complexe. Din clasa streambuf derivă clasele strstreambuf şi filebuf.

3

Clasa ios are un pointer către streambuf. Ea are date pentru a gestiona interfaţa cu streambuf şi pentru tratarea erorilor.

Din clasa ios derivă clasele istream pentru gestionarea intrărilor şi clasa ostream pentru gestionarea ieşirilor.

La prelucrarea fişierelor se folosesc obiecte ale clasei filebuf.

Sunt folosite următoarele clase:- ifstream folosită pentru operaţii de intrare (citire)

4

- ofstream folosită pentru operaţii de ieşire(scriere)

- fstream folosită pentru operaţii de intrare/ieşire (citire/scriere)

■ Pentru obiectele acestor clase se pot aplica funcţiile membru ale claselor de bază, inclusiv supraîncărcarea operatorilor de inserare şi extragere.

■ Prelucarea unui fişier începe cu deschiderea lui. În acest scop se poate proceda în 2 moduri:

5

1. Se utilizează funcţia open cu un obiect al uneia din clasele ifstream, ofstream sau fstream instanţiat fără parametri;

2. Se utilizează parametri pentru deschiderea fişierului la instanţierea obiectelor;

În primul caz, obiectele se instanţiază folosind constructori impliciţi;

De exemplu, fie instanţierea:ifstream fisier1;

Obiectului fisier1 i se ataşează un fişier concret la un apel al funcţieifisier1.open(...)

6

Funcţia open este definită în clasa fstreambase şi este supraîncărcată în clasele derivate din aceasta. Ea are prototipul:void open(char *fisier,int mod,int protectie);

Parametrul fisier este un pointer spre un şirde caractere care defineşte numele şiextensia fişierului care se deschide, precumşi calea spre fişierul respectiv, dacă nu se află în directorul curent.

Parametrul mod defineşte modul de deschi-dere al fişierului. În acest scop se pot folosi enumeratorii definiţi în clasa ios astfel:

7

in - fişierul se deschide în intrare (citire); out – fişierul se deschide în ieşire (scriere); ate – după deschiderea fişierului, poziţia

curentă în fişier este sfârşitul fişierului; acest mod se utilizează pentru a face căutări în fişier începând cu sfârşitul acestuia;

app – deschidere pentru a adăuga înregistrări trunc – dacă fişierul există, conţinutul lui se

pierde şi se crează un fişier nou. Acest mod este implicit când este prezentă opţiunea out (deschidere în scriere) şi este incompatibil cu opţiunile ate şi app;

8

nocreate – dacă fişierul există şi este prezen-tă opţiunea out, atunci deschiderea este admisă numai dacă se utilizează opţiunea ate sau app.

binary – fişierul se deschide pentru a putea fi prelucrat binar. În mod implicit fişierele se consideră că sunt prelucrate pe caractere (mod text).

La deschidere de fişier se pot folosi împreună mai multe opţiuni folosind operatorul sau logic (“|”)

9

■ Pentru obiectele clasei ifstream, opţiunea ineste implicită, iar pentru cele ale claseiofstream, opţiunea out este implicită.

Parametrul protectie defineşte modul de acces la fişier. În mod implicit acest parame-tru are valoarea zero şi aceasta înseamnă că fişierul respectiv nu are restricţii la acces.

Rezultatul operaţiei de deschidere poate fi testat cu ajutorul cuvâtului de stare al streamului pentru care s-a apelat funcţia open.

10

Exemple1. ifstream fisier;// se deschide fisierul fis.dat in citire

fisier.open(“fis.dat”,ios::nocreate);// se testeaza starea obiectului fisier dupa deschidere

if(fisier){// deschidere corecta

…}else{

…cout<<“Incident la deschidere fisier fis.dat\n”;…}

11

Exemple Opţiunea ios::in este implicită.

2. ofstream fis_iesire;//se deschide in scriere fisierul factura.dat

fis_iesire.open(“factura.dat”);if(!fis_iesire){ cout<<“Incident la deschidere;

…}

12

Exemple3. ofstream fis;//se deschide pentru adugare fisierul binar //stoc.dat

fis.open(“stoc.dat”,ios::app|ios::binary);// se testeaza starea obiectului fis dupa deschidereif(!fis){

cout<<“Incident la deschidere”;…}else {

…//deschidere corecta}

13

Cea de-a doua posibilitate de deschidere a unui fişier este folosirea parametrilor corespunzători la instanţierea obiectelor claselor ifstream, ofstream sau fstream.

În acest caz constructorul apelat pentru instanţierea obiectelor claselor amintite mai sus au aceeaşi parametri ca şi funcţia open:

nume_clasa(char *fisier,int mod, int protectie)unde:nume_clasa este ifstream, ofstream, fstream. Parametru protectie este şi în acest caz un

parametru implicit cu valoare zero.

14

Exemplele anterioare pot fi rescrise astfel1. ifstream fisier(“fis.dat”,ios::nocreate);

if(fisier){//deschidere corecta

…}else { cout<<“Incident la deschidere”;…}

2. ofstream fis_iesire(“factura.dat”);if(!fis_iesire){ cout<<“Incident la deschidere;

…}

15

Exemplul 3

ofstream fis (“stoc.dat”,ios::app | ios::binary);if(!fis){

cout<<“Incident la deschidere”;…}

else { …//deschidere corecta}

16

După deschiderea unui fişier se pot face prelucrări pe el;

După terminarea prelucrării, în conformitate cu modul în care a fost deschis, acesta trebuie să fie închis;

Închiderea se realizează cu funcţia close. Aceasta se apelează astfel:

obiect.close();sau

pobiect->close();unde:obiect – este o instanţă a uneia dintre clasele ifstream,

ofstream sau fstream.

17

În mod analog, pobiect este un pointer spre unul din tipurile implementate prin aceste clase.

Funcţiile membre get, getline, put, read şi write pot fi folosite pentru a realiza operaţii de intrare/ieşire cu acces secvenţial.

Accesul aleator se poate realiza folosind funcţiile membru specifice ale claselor ostream şi istream.

Clasa ostream are funcţiile membru seekp şi tellp care pot fi utilizate la realizarea accesu-lui aleator la scrierea înregistrărilor în fişiere.

18

În mod analog, clasa istream are funcţiile membru seekg şi tellg care pot fi utilizate la realizarea accesului aleator la citirea înregis-trărilor în fişiere.

Funcţia tellp returnează poziţia curentă din stream faţă de începutul lui. Are prototipul:long tellp();

Funcţia seekp realizează poziţionarea în streamul curent. Are prototipul:ostream&seekp(long n,seek_dir rel=beg);

unde:seek_dir se defineşte în clasa ios astfel:

19

enum seek_dir{beg,cur,end}; Aceşti parametri au următoarea semnificaţie:- n deplasament în număr de octeţi;- rel=beg deplasamentul se consideră faţă de

începutul streamului;- rel=cur deplasamentul se consideră faţă de

poziţia curentă din stream;- rel=end deplasamentul se consideră faţă de

sfârşitul streamului.

20

Funcţiile membre ale clasei istream au prototipuri şi semnificaţii similare;

long tellg();şi

istream&seelg(long n,seek_dir rel=beg); De menţionat că funcţiile tellp, tellg, seekp,

seekg se pot utiliza şi în legătură cu obiecte ale claselor istrstream, ostrstream şi strstream.

21

O altă funcţie utilă este gcount, funcţie membră a clasei istream.

Ea are prototipul:int gcount();

Returnează numărul de octeţi citiţi la ultima operaţie de intrare.

22

Aplicaţie: fismisc.cpp

Să se scrie un program care citeşte de la intrarea standard datele ale căror formate sunt definite mai jos şi le scrie în fişierul misc.dat din directorul curent.Fişierul este organizat binar, fiecare articol conţinând următoarele câmpuri:

100010123456mcablu electricIcantitatepreţcodumdenumiretip

23

Aplicaţie : fismisc1.cpp

Să se scrie un program care afişează articolele din fişierul misc.dat creat anterior , pentru tip=I.

I=intrariE=iesiriT=transfer

24

Aplicaţie: fistext.cpp

Să se scrie un program care citeşte şiruri de caractere şi le transferă pe disc.