Sunteți pe pagina 1din 56

Parametrizare (Programare generic) - plan

Clase parametrizate
Declaraie template Definirea membrilor Instaniere (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, funcii template Programatorul scrie o singur definiie template iar C++, pe baza parametrilor, genereaz specializri care sunt compilate cu restul programului surs O funcie template poate fi suprancrcat cu:
Funcii template cu acelai nume dar parametri template diferii Funcii non template cu acelai nume dar cu ali 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 aceluiai nume pentru mai multe nelesuri(polimorfism). nelesul este dedus din tipul parametrilor (parametric).
Gh GRIGORAS 4

POO(C++)

Funcie 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

Funcie generic de sortare:

Template-uri

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 template <class T> void DisplayBox<T>::setValue(T newValue) { value = newValue; utilizare }

parametriza te

parametri
10

D. Lucanu

POO Principii

Clase template (parametrizate)


Declaraie 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::= declaraia unei clase sau funcii
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
Funciile membru ale unei clase template sunt funcii template parametrizate cu parametrii clasei template respective Definirea membrilor unei clase template:
Definiie inline, la specificarea clasei nu este specificat explicit template Definiie n afara specificrii 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
Instaniere template: procesul de generare a unei declaraii de clas (funcie) de la o clas(funcie) template cu argumente corespunztoare
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: Suprancrcare 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

Specializri
O versiune a unui template pentru un argument template particular este numit o specializare O definiie alternativ pentru o clas(funcie) template ( de ex. pentru a funciona cnd argumentul template este pointer) este numit specializare definit de utilizator

POO(C++)

Gh GRIGORAS

23

Clase parametrizate - Specializri


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;

Specializri:

POO(C++)

Gh GRIGORAS

24

Clase parametrizate - Specializri


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 - Specializri


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 instanieri ale unei clase template sunt echivalente dac parametrii template ce reprezint tipuri sunt aceeai iar ceilali au aceleai valori
MyString<char> s1; MyString<unsigned char> s2; typedef unsigned char Uchar; MyString <Uchar> s3;

POO(C++)

Gh GRIGORAS

27

Clase parametrizate relaia friend


Funcii(clase) friend n clase template:
Dac funcia friend acceseaz un parametru template, aceasta trebuie s fie template. n acest caz o instaniere este friend doar pentru instanierile clasei template cu aceiai parametri (friend legat).

Prieteni template nelegai - are ali parametri template


Dac funcia friend nu acceseaz parametri template , este friend pentru toate instanierile clasei
POO(C++) Gh GRIGORAS 28

Clase parametrizate relaia 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 funcii Datele statice trebuiesc iniializate, global sau pe specializri
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 obinuit

Se poate defini o clas obinuit 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> conine informaii 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 ieire) este un mecanism pentru conversia valorilor de diverse tipuri n secvene 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, fiierul <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 spaiile la intrare Ignor spaiile Nu ignor spaiile 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
Notaia tiinific pentru numere reale Notaia punct fix pentru numere reale Aliniere stnga Aliniere dreapta Caract. de umplere intre semn si valoare Seteaza dimensiunea cmpului Caracterul c nlocuete 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

Funcii 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

Fiiere
ntr-un program C++ fluxurile standard cin, cout, cerr, clog sunt disponibile; corespondena lor cu dispozitivele (fiierele ) standard este fcut de sistem Programatorul poate crea fluxuri proprii obiecte ale clasei fstream (ifstream, ofstream). Ataarea fluxului creat unui fiier 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

Fiiere
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

Fiiere 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

Fiiere de ieire
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, poziionare la sfrit nainte de fiecare inserie ate, poziionare la sfrit la deschiderea fiierului binary, citirea fiierului n mod binar i nu n mod text in, permite extragerea (fiier de intrare) out, permite inseria (fiier de ieire) trunc, trunchiaz un fiier 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 fiiere:
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