Você está na página 1de 56

Parametrizare (Programare generic ) - plan

Clase parametrizate
Declara ie template Definirea membrilor Instan iere (Specializare), Specializare utilizator Friend n template Membri statici n template

Derivare - parametrizare Ierarhia de clase STL:: IOS

POO(C++)

Gh GRIGORAS

Clase parametrizate
Programare generic : programare ce utilizeaz tipurile ca parametri n C++ - mecanismul template: clase template, func ii template Programatorul scrie o singur defini ie template iar C++, pe baza parametrilor, genereaz specializ ri care sunt compilate cu restul programului surs O func ie template poate fi supranc rcat cu:
Func ii template cu acela i nume dar parametri template diferi i Func ii non template cu acela i nume dar cu al i parametri

Clasele template se mai numesc tipuri parametrizate


POO(C++) Gh GRIGORAS 2

Template-uri
//Supraincarcare functii void swap(int& x, int& y){ int aux = x; x = y; y = aux; } void swap(char& x, char& y){ char aux = x; x = y; y = aux; } void swap(float& x, float& y){ float aux = x; x = y; y = aux; }
POO(C++) Gh GRIGORAS 3

Template-uri
int x = 23, y = 14; char c1 = 'o', c2 = '9'; double u = .5, v = 5.5; swap(x, y); swap(u, v); swap(c1, c2);

Polimorfism parametric:

utilizarea aceluia i nume pentru mai multe n elesuri(polimorfism). n elesul este dedus din tipul parametrilor (parametric).
Gh GRIGORAS 4

POO(C++)

Func ie generic de interschimbare:


template <class T> void swap(T& x, T& y) { tip aux = x; x = y; y = aux; } int m = 8, n = 15; swap(m, n); // swap<int>(m, n); cout << endl << m << ", " << n << endl; double a = 10.0, b = 20.0; swap(a,b); // swap<double>(m, n); cout << endl << a << ", " << b << endl; complex z1(1.2, 2.3), z2(5.5, 2.2); swap(z1, z2); // swap<complex>(m, n);

Template-uri

POO(C++)

Gh GRIGORAS

Template-uri
Func ie generic de sortare:
template <class T> void naiveSort(T a[], int n) { for (int i=0; i<n-1; i++) for(int j=i+1; j<n; j++) if (a[i] > a[j]) swap<T>(a[i], a[j]); };

Parametrii generici pot fi i tipuri de baz


template <class T, int n> void naivSort2(T a[]) { for (int i=0; i<n-1; i++) for(int j=i+1; j<n; j++) if (a[i] > a[j]) swap<T>(a[i], a[j]); };

POO(C++)

Gh GRIGORAS

Template-uri
La apel, pentru n trebuie transmis o constant :
int i; double x[5] = {2,1,3,5,4}; naivSort<double>(x, 5); for (i=0; i<5; i++) cout << x[i] << ", "; cout << endl; double y[5] = {2,1,3,5,4}; naivSort2<double, 5>(y); for (i=0; i<5; i++) cout << x[i] << ", "; cout << endl; int n = 5; double z[5] = {2,1,3,5,4}; naivSort2<double, n>(z);

// eroare

POO(C++)

Gh GRIGORAS

Abstractizare prin parametrizare


void setValue(string newValue) { value = newValue; } poate fi parametrizat? void setValue(double newValue) { value = newValue; }

D. Lucanu

POO Principii

Clase parametrizate
parametru parametru

D. Lucanu

POO Principii

Clase parametrizate in C++


template <class T> class DisplayBox { declaratie private: string label; parametri private: T value; public: DisplayBox(char *newLabel = ""); public: void setValue(T newValue); }; definitii parametriza te template <class T> void DisplayBox<T>::setValue(T newValue) { value = newValue; utilizare } parametri
D. Lucanu POO Principii 10

Clase template (parametrizate)


Declara ie template:
template < lista_argumente_template > declaratie lista_argumente_template ::= argument_template| lista_argumente_template, argument_template argument_template ::= tip_argument|declaratie_argument tip_argument ::= class identificator|typename identificator declaratie_argument::=<tip> identificator declaratie::= declara ia unei clase sau func ii

POO(C++)

Gh GRIGORAS

11

Clase parametrizate
template< class T, int i > class MyStack{}; template< class T1, class T2 > class X{}; template< typename T1, typename T2 > class X{}; template<class T> class allocator {}; template<class T1, typename T2 = allocator<T1> > class stack { }; stack<int> MyStack; // al doilea argument este implicit class Y {...}; template<class T, T* pT> class X1 {...}; template<class T1, class T2 = T1> class X2 {...}; Y aY; X1<Y, &aY> x1; X2<int> x2;

POO(C++)

Gh GRIGORAS

12

Clase parametrizate
Func iile membru ale unei clase template sunt func ii template parametrizate cu parametrii clasei template respective Definirea membrilor unei clase template:

Defini ie inline, la specificarea clasei nu este specificat explicit template Defini ie n afara specific rii clasei trebuie declarat explicit template:

template <lista_argumente_template > nume_clasa_template<argum>::nume_functie_membru(parametri) { //Corp functie }

Compilatorul nu aloc memorie la declararea unui template


POO(C++) Gh GRIGORAS 13

Clase parametrizate
Instan iere template: procesul de generare a unei declara ii de clas (func ie) de la o clas (func ie) template cu argumente corespunz toare
template class MyStack<class T,int n>{}; template class MyStack<int, 6>; template MyStack<int, 6>::MyStack(); template<class T> void f(T) {...} template void f<int> (int); template void f(char);
POO(C++) Gh GRIGORAS 14

Clase parametrizate Exemplul 1


template <class Elt> class Cell { public: Cell(); Cell(const Cell&); // constructor de copiere ~Cell(); Elt getVal() const; void setVal(Elt); Cell& operator=(const Cell&); private: Elt* val; }; template <class Elt> Cell<Elt>::Cell() { val = new Elt; }

POO(C++)

Gh GRIGORAS

15

Exemplul 1 - cont
template <class Elt> Cell<Elt>::Cell(const Cell<Elt>& c) { val = new Elt; *val = *(c.val); } template <class Elt> Cell<Elt>::~Cell() { delete val; } template <class Elt> Cell<Elt>& Cell<Elt>::operator =(const Cell<Elt>& c) { //.. *val = *(c.val); return *this; }
POO(C++) Gh GRIGORAS 16

Exemplul 1 - cont
#include "cell.h" template <class Elt> class Array { public: Array(int = 1); Array(const Aray&); ~Array(); Elt get(int); void set(int, Elt); Array& operator=(const Array&); Cell<Elt>& operator[](int) const Cell<Elt>& operator[](int) const; private: Cell<Elt> *arr; int nOfComp; };

POO(C++)

Gh GRIGORAS

17

Exemplul 1 - cont
template <class Elt> Array<Elt>::Array(int nMax) { arr = new Cell<Elt>[nMax]; if(arr == NULL) throw Memorie insuficienta "; nOfComp = nMax; }; template <class Elt> Array<Elt>::~Array() { delete[] arr; }; template <class Elt> Elt Array<Elt>::get(int i) { if((i<0)||(i>=nOfComp)) throw "Index gresit."; return arr[i].getVal(); };
POO(C++) Gh GRIGORAS 18

Exemplul 1 - cont
Template: Supranc rcare operatori
template <class Elt> Cell<Elt>& Array<Elt>::operator[](int i) { if((i<0)||(i>=nOfComp)) throw "Index gresit."; return arr[i]; }

// pentru a sorta tablouri de celule de int-uri // trebuie definit operatorul de comparare: bool operator >(const Cell<int>& x, const Cell<int>& y) { return x.getVal() > y.getVal(); }

POO(C++)

Gh GRIGORAS

19

Exemplul 1 - cont
// sortare prin insertie template <class T> void insert_sort(Array<T>& a, int n) { int i,j; Cell<T> temp; for(i=1;i<n;i++) { temp = a[i]; j = i - 1 ; while((j >= 0) && (a[j] > temp)) { a.set(j+1, a[j].getVal()); j--; } if (i != (j-1)) a.set(j+1, temp.getVal()); } } typedef Cell<int> Int; typedef Cell<char> Char;
POO(C++) Gh GRIGORAS 20

Clase parametrizate - Exemplul 2


template <class T> class Vector { public: Vector(int=0); T& operator [](int); const T& operator [](int) const; // private: T* tab; int n; }; template <class T> class Matrice { public: Matrice(int=0, int=0); Vector<T>& operator [](int); const Vector<T>& operator [](int) const; private: Vector<T>* tabv; int m, n; };
POO(C++) Gh GRIGORAS 21

Exemplul 2
template <class T> T& Vector<T>::operator [](int i) { cout << "Vector<T>::operator [](int i)" << endl; return tab[i]; } template <class T> const Vector<T>& Matrice<T>::operator [](int i) const { cout << "Matrice<T>::operator [](int i) const" << endl; if (i < 0 || i >= m) throw "index out of range"; return tabv[i]; } Vector<int> v(5); v[3] = 3; // apel varianta nonconst const Vector<int> vv(5); vv[4] = 4;// apel varianta const Matrice<double> m(3,5); m[1][2] = 5.0; const Matrice<double> mm(3,5); mm[2][3] = 7.0;

POO(C++)

Gh GRIGORAS

22

Specializ ri
O versiune a unui template pentru un argument template particular este numit o specializare

O defini ie alternativ pentru o clas (func ie) template ( de ex. pentru a func iona cnd argumentul template este pointer) este numit specializare definit de utilizator

POO(C++)

Gh GRIGORAS

23

Clase parametrizate - Specializ ri


template <class T> class Vector { public: Vector(int=0); T& operator [](int); const T& operator [](int) const; private: T* tab; int n; }; Vector<int> vi; Vector<Punct*> vpp; Vector<string> vs; Vector<char*> vpc;

Specializ ri:

POO(C++)

Gh GRIGORAS

24

Clase parametrizate - Specializ ri


Specializare a clasei Vector<T> pentru pointeri la void:
template<> class Vector<void*>{ // specializare fara parametri template void** p; // };

Specializare a clasei Vector<T> pentru pointeri la T:


template<class T> class Vector<T*>{ // specializare cu parametri template // };
POO(C++) Gh GRIGORAS 25

Clase parametrizate - Specializ ri


template <class T> void swap(T& x, T& y){ T t = x; x = y; y = t; }

Specializare pentru Vector<T> :


template <class T> void swap(Vector<T>& a, Vector<T>& b){ a.swap(b); }

n clasa Vector<T>, metoda:


template <class T> void Vector<T>:: swap(Vector<T>& a){ swap(tab, a.tab); swap(n, a.n); }
POO(C++) Gh GRIGORAS 26

Clase parametrizate
Dou instan ieri ale unei clase template sunt echivalente dac parametrii template ce reprezint tipuri sunt aceea i iar ceilal i au acelea i valori
MyString<char> s1; MyString<unsigned char> s2; typedef unsigned char Uchar; MyString <Uchar> s3;

POO(C++)

Gh GRIGORAS

27

Clase parametrizate rela ia friend


Func ii(clase) friend n clase template:
Dac func ia friend acceseaz un parametru template, aceasta trebuie s fie template. n acest caz o instan iere este friend doar pentru instan ierile clasei template cu aceia i parametri (friend legat ). Prieteni template nelega i - are al i parametri template Dac func ia friend nu acceseaz parametri template , este friend pentru toate instan ierile clasei
POO(C++) Gh GRIGORAS 28

Clase parametrizate rela ia friend


template <class T> class X { //.. friend void f1(); // f1 friend pentru toate specializarile friend void f2(X<T>& ); // f2(X<float>&) friend pentru X<float> friend class Y; friend class Z<T>; friend void A::f3(); friend void C<T> :: f4(X<double>&); // };

POO(C++)

Gh GRIGORAS

29

Membri statici n template uri


Fiecare specializare a unei clase template are copia proprie a membrilor static, att date ct i func ii Datele statice trebuiesc ini ializate, global sau pe specializ ri
template<class T, int n> class ClasaN{ static const int cod; // }; template<class T, int n> const int ClasaN<T, n>::cod = n; template<> const int ClasaN<int, 10>::cod =50
POO(C++) Gh GRIGORAS 30

Derivare - parametrizare
Se poate defini o clas parametrizat prin derivare
de la o clas parametrizat de la o instan a unei clase parametrizate de la o clas obi nuit

Se poate defini o clas obi nuit prin derivare de la o instan a unei clase parametrizate
POO(C++) 2005-2006 Gh GRIGORAS 31

Derivare - parametrizare
template <class T> class Fisier: protected fstream {}; template <class T> class FisierCitire: public virtual Fisier<T> {}; template <class T> class FisierScriere: public virtual Fisier<T> {}; template <class T> class FisierCitireScriere: public FisierCitire<T>, public FisierScriere<T> {};
POO(C++) 2005-2006 Gh GRIGORAS 32

Derivare i parametrizare - Exemplu


template <class TYPE> class stack { public: explicit stack(int size = 100) // doar explicit : max_len(size), top(EMPTY) {s = new TYPE[size]; assert (s != 0);} ~stack() { delete []s; } void reset() { top = EMPTY; } void push(TYPE c) { s[++top] = c; } TYPE pop() { return s[top--]; } TYPE top_of()const { return s[top]; } bool empty()const { return top == EMPTY;} bool full()const { return top == max_len - 1;} private: enum { EMPTY = -1 }; TYPE* s; int max_len; int top; };
POO(C++) 2005-2006 Gh GRIGORAS 33

Derivare i parametrizare - Exemplu


class safe_char_stack : public stack<char> { public: // push, pop sigure void push(char c) { assert (!full()); stack<char>::push(c); } char pop() {assert (!empty()); return (stack<char>::pop());} }; template <class Type> class safe_stack : public stack<Type> { public: // push, pop sigure void push(Type c) { assert (!full()); stack<Type>::push(c); } char pop() {assert (!empty()); return (stack<Type>::pop());} };
POO(C++) 2005-2006 Gh GRIGORAS 34

Ierarhia de clase STL:: IOS


ios_base Mostenire virtuala ios<>
istream<>

ostream<>

istringstream<> ifstream<> iostream<>

ostringstream<> ofstream<>

fstream<>

stringstream<>

POO(C++) 2005-2006

Gh GRIGORAS

35

Ierarhia de clase iostream


Clasele cu sufixul <> sunt template - uri parametrizate cu un tip caracter iar numele lor au prefixul basic_ :
template <class E, class T = char_traits<E> > class basic_ios : public ios_base { // };

char_traits<E> con ine informa ii pentru manipularea elementelor de tip E


template <class E, class T = char_traits<E> > class basic_istream : virtual public basic_ios<E, T> { // };
POO(C++) 2005-2006 Gh GRIGORAS 36

Ierarhia de clase streambuf

streambuf<>

filebuf<>

stringbuf<>

POO(C++) 2005-2006

Gh GRIGORAS

37

Clasa basic_iostream
template <class E, class T = char_traits<E>> class basic_iostream : public basic_istream<E, T>, public basic_ostream<E, T> { public: explicit basic_iostream(basic_streambuf<E, T>* sb); virtual ~basic_iostream(); };

POO(C++) 2005-2006

Gh GRIGORAS

38

Fisierul header <iosfwd>


typedef basic_ios<char, char_traits<char> > ios; typedef basic_istream<char, char_traits<char> > istream; typedef basic_ostream<char, char_traits<char> > ostream; typedef typedef typedef typedef basic_iostream<char, char_traits<char> > basic_ifstream<char, char_traits<char> > basic_ofstream<char, char_traits<char> > basic_fstream<char, char_traits<char> > iostream; ifstream; ofstream; fstream;

POO(C++) 2005-2006

Gh GRIGORAS

39

Clasa ostream
Un obiect din ostream (flux de ie ire) este un mecanism pentru conversia valorilor de diverse tipuri n secven e de caractere n <iostream>:
ostream cout; //fluxul standard de iesire ostream cerr; // mesaje eroare,fara buffer ostream clog; // mesaje eroare,cu buffer

POO(C++) 2005-2006

Gh GRIGORAS

40

operator<< (n ostream)
basic_ostream& operator<< (const char *s); basic_ostream& operator<< (char c); basic_ostream& operator<< (bool n); basic_ostream& operator<< (short n); basic_ostream& operator<< (unsigned short n); basic_ostream& operator<< (int n); basic_ostream& operator<< (unsigned int n); basic_ostream& operator<< (long n); basic_ostream& operator<< (unsigned long n); basic_ostream& operator<< (float n); basic_ostream& operator<< (double n); basic_ostream& operator<< (long double n); basic_ostream& operator<< (void * n); basic_ostream& put(E c); // scrie c basic_ostream& write(E *p, streamsize n); // scrie p[0],,p[n-1] basic_ostream& flush(); // goleste bufferul pos_type tellp(); // pozitia curenta basic_ostream& seekp(pos_type pos); // noua positie pos basic_ostream& seekp(off_type off, ios_base::seek_dir way); // pozitia way (= beg, cur, end) + off

POO(C++) 2005-2006

Gh GRIGORAS

41

Formatare, fi ierul <iomanip>


void main() { int i = 10, j = 16, k = 24; cout << i << '\t' << j << '\t' << k << endl; cout << oct << i << '\t' << j << '\t' << k << endl; cout << hex << i << '\t' << j << '\t' << k << endl; cout << "Introdu 3 intregi: " << endl; cin >> i >> hex >> j >> k; cout << dec << i << '\t' << j << '\t' << k << endl; } /* 10 16 24 12 20 30 a 10 18 Introdu 3 intregi: 42 11 12a 42 17 298 */

POO(C++) 2005-2006

Gh GRIGORAS

42

Manipulatori
MANIPULATOR
endl ends flush dec hex oct ws skipws noskipws showpoint noshowpoint showpos noshowpos boolalpha noboolalpha POO(C++) 2005-2006 Scrie newline Scrie NULL in string Goleste Baza 10 Baza 16 Baza 8 Ignor spa iile la intrare Ignor spa iile Nu ignor spa iile Se scrie punctul zecimal i zerourile Nu se scriu zerourile, nici punctul Scrie + la numerele nenegative Nu scrie + la numerele nenegative Scrie true si false pentru bool Scrie 1 si 0 pentru bool Gh GRIGORAS

EFECTUL

FISIERUL
iostream iostream iostream iostream iostream iostream iostream iostream iostream iostream iostream iostream iostream iostream iostream 43

Manipulatori
MANIPULATOR
scientific fixed left right internal setw(int) setfill(char c) setbase(int) setprecision(int) setiosflags(long) resetiosflags(long)

EFECTUL
Nota ia tiin ific pentru numere reale Nota ia punct fix pentru numere reale Aliniere stnga Aliniere dreapta Caract. de umplere intre semn si valoare Seteaza dimensiunea cmpului Caracterul c nlocue te blancurile Setarea bazei Seteaza precizia in flotant Seteaza bitii pentru format Reseteaza bitii pentru format

FISIERUL
iostream iostream iostream iostream iostream iomanip iomanip iomanip iomanip iomanip iomanip

POO(C++) 2005-2006

Gh GRIGORAS

44

double a = 12.05, b = 11.25, c = -200.89; cout << a << ',' << b << ',' << c << endl; cout << setfill('*') << setprecision(3); cout << setw(10) << a << endl; cout << setw(10) << b << endl; cout << setw(10) << c << endl; cout << setw(10) << showpoint << c << endl; cout << setfill(' ') << right << showpoint; cout << setw(15) << setprecision(5) << c << endl; cout << scientific << c << endl; char d; cin >> noskipws; while(cin >>d) cout << d;
12.05,11.25,-200.89 ******12.1 ******11.3 ******-201 *****-201. -200.89 -2.00890e+002 text pentru test text pentru test
POO(C++) 2005-2006 Gh GRIGORAS 45

Clasa istream
Un obiect din istream (flux de intrare) este un mecanism pentru conversia caracterelor n valori de diverse tipuri n <iostream>: istream cin; //fluxul standard de intrare n basic_istream este definit operator>> pentru tipurile fundamentale

POO(C++) 2005-2006

Gh GRIGORAS

46

Func ii utile n istream


streamsize gcount() const; int_type get(); basic_istream& get(E& c); basic_istream& get(E *s, streamsize n); basic_istream& get(E *s, streamsize n, E delim); basic_istream& get(basic_streambuf<E, T> *sb); basic_istream& get(basic_streambuf<E, T> *sb, E delim); basic_istream& getline(E *s, streamsize n); basic_istream& getline(E *s, streamsize n, E delim); basic_istream& ignore(streamsize n = 1, int_type delim = T::eof()); int_type peek(); // citeste fara a-l extrage basic_istream& read(E *s, streamsize n); streamsize readsome(E *s, streamsize n); // peek cel mult n basic_istream& putback(E c); // pune c in buferul de intrare basic_istream& unget(); // pune inapoi ultimul citit pos_type tellg(); basic_istream& seekg(pos_type pos); basic_istream& seekg(off_type off, ios_base::seek_dir way); int sync(); // flush input

POO(C++) 2005-2006

Gh GRIGORAS

47

Fi iere
ntr-un program C++ fluxurile standard cin, cout, cerr, clog sunt disponibile; coresponden a lor cu dispozitivele (fi ierele ) standard este f cut de sistem Programatorul poate crea fluxuri proprii obiecte ale clasei fstream (ifstream, ofstream). Ata area fluxului creat unui fi ier sau unui string se face de programator:
la declarare cu un constructor cu parametri dup declarare prin mesajul open()
POO(C++) 2005-2006 Gh GRIGORAS 48

Fi iere
Constructorii clasei fstream:
explicit basic_fstream(); explicit basic_fstream(const char *s, ios_base::openmode mode = ios_base::in | ios_base::out);

Metode:
bool is_open() const; void open(const char *s, ios_base::openmode mode = ios_base::in | ios_base::out); void close();
POO(C++) 2005-2006 Gh GRIGORAS 49

Fi iere de intrare
Constructorii clasei ifstream:
explicit basic_ifstream(); explicit basic_ifstream(const char *s, ios_base::openmode mode = ios_base::in);

Metode:
bool is_open() const; void open(const char *s, ios_base::openmode mode = ios_base::in); void close();
POO(C++) 2005-2006 Gh GRIGORAS 50

#include <fstream> #include <iostream> #include <string> using namespace std; int main () { string line; ifstream myfile ("file.cpp"); if (myfile.is_open()) { while (! myfile.eof() ) { getline (myfile,line); cout << line << endl; } myfile.close(); }else cout << "Unable to open file"; return 0; }
POO(C++) 2005-2006 Gh GRIGORAS 51

Fi iere de ie ire
Constructorii clasei ofstream:
explicit basic_ofstream(); explicit basic_ofstream(const char *s, ios_base::openmode which = ios_base::out | ios_base::trunc);

Metode:
bool is_open() const; void open(const char *s, ios_base::openmode mode = ios_base::out | ios_base::trunc); void close();
POO(C++) 2005-2006 Gh GRIGORAS 52

#include <iostream> #include <fstream> using namespace std; int main () { ofstream myfile ("example.txt"); if (myfile.is_open()){ myfile << "This is a line.\n"; myfile << "This is another line.\n"; myfile.close(); } else cout << "Unable to open file"; return 0; }
POO(C++) 2005-2006 Gh GRIGORAS 53

ios_base::openmode
app, pozi ionare la sfr it nainte de fiecare inser ie ate, pozi ionare la sfr it la deschiderea fi ierului binary, citirea fi ierului n mod binar i nu n mod text in, permite extragerea (fi ier de intrare) out, permite inser ia (fi ier de ie ire) trunc, trunchiaz un fi ier existent la prima creare a fluxului ce-l controleaz
POO(C++) 2005-2006 Gh GRIGORAS 54

Clasa stringstream
Permite ca stringurile s fie tratate ca fi iere:
explicit basic_stringstream(ios_base::openmode mode = ios_base::in | ios_base::out); explicit basic_stringstream(const basic_string<E,T,A>& x, ios_base::openmode mode = ios_base::in | ios_base::out);

POO(C++) 2005-2006

Gh GRIGORAS

55

#include <iostream> #include <sstream> using namespace std; int main() { stringstream s("This is initial string."); // get string string str = s.str(); cout << str << endl; // output to string stream s << "Numbers: " << 10 << " " << 123.2; int i; double d; s >> str >> i >> d; cout << str << " " << i << " " << d; return 0; }

POO(C++) 2005-2006

Gh GRIGORAS

56

Você também pode gostar