Sunteți pe pagina 1din 20

Universitatea Tehnic Gheorghe Asachi din Iai Facultatea de Automatic i Calculatoare

PROGRAMARE ORIENTAT OBIECT


Curs 9 Template

Template

Necesitatea parametrizrii tipului de date

Fie funcia ce realizeaz suma elementelor unui vector de elemente de tip double
double Sum0(double* a, int n) { double res = 0;
for(int i = 0; i < n; ++i) { res += a[i]; } return res; }

Necesitatea parametrizrii tipului de date

Fie un vector cu elemente de tip float. Poate fi utilizaz funcia Sum0 pentru suma elementelor?
double float // ... double float a[10]; b[10];

sa = sum0(a, 10); // OK sb = sum0(b, 10); // eroare de compilare Soluie clasic: float Sum0(float* a, int n) { float res = 0; for(int i = 0; i < n; ++i) { res += a[i]; } return res; }

Cum se poate generaliza aceast funcie ?

Necesitatea parametrizrii tipului de date


Pentru majoritatea tipurilor de date utilizate ar trebui definit cte o funcie Spaiul ocupat de program crete Posibilitatea de trimite tipul de date ca parametru ar permite existena unei singure funcii pentru suma elementelor unui vector template<typename T>
T sum1(T* a, int n) { T res = 0; for(int i = 0; i < n; ++i) { res += a[i]; } return res; }

Necesitatea parametrizrii tipului de date


double float int // ... double float int a[10]; b[10]; c[10]; sa = sum1(a, 10); // OK sb = sum1(b, 10); // OK sc = sum1(c, 10); // OK

Introducere

Template-urile (abloane) furnizeaz suport pentru programare generic utiliznd tipurile de date ca parametri Mecanismul template al limbajului C++ permite ca un tip de date sau o valoare s fie un parametru n definirea unei clase, funcii sau alias. Template-urile furnizeaz o cale direct de a reprezenta o gam larg de concepte generale i ci simple de a le combina. Rezultatul din punct de vedere al claselor i funciilor poate fi un cod mai puin general la run-time i eficient din punct de vedere al spaiului. Template-urile au fost introduse avnd ca scop proiectarea, implementarea i utilizarea librriei standard. Librria standard cere un mare grad de generalitate, flexibilitate i eficien.

Introducere

n consecin, tehnicile care pot fi utilizate n proiectarea i implementarea libriei standard sunt eficace i eficiente n proiectarea soluiilor pentru o mare varietate de probleme. Aceste tehnici permite unui programator s ascund implementri sofisticate n spatele unei simple interfee i s expun complexitatea utilizatorului atunci cnd acesta are nevoie i cere acest lucru.

Un simplu template string

Se consider un ir de caractere definit ca o clas ce memoreaz caractere i furnizeaz operaii precum cautare, comparare, concaternare. Se dorete ca acest comportament s poate fi aplicat mai multor tipuri de carcatere: char, unsigned char, caractere chinezeti, caractere greceti etc. Cu alte cuvinte se dorete reprezentarea noiiunii de ir de caractere cu o depende ct mai mic de un specific tip de caracter

String template

Fie clasa String:


class String { char *ptr; int sz; public: String() : sz(0), ptr(0) {}; explicit String(const char*p); String(const String&); char& operator[](int n) { return ptr[n]; } String& operator+=(char c); String& operator=(const String&); String() { if (ptr) delete[] ptr; } };

Clasa gestioneaz iruri de caractere de tip char. Pentru a deveni o clas general se parametrizeaz tipul de date

String template
template<typename T> class String { T *ptr; int sz; public: String() : sz(0), ptr(0) {}; explicit String(const T*p); String(const String&); T& operator[](int n) { return ptr[n]; } String& operator+=(T c); String& operator=(const String&); String(String&& x); ~String() { if (ptr) delete[] ptr; } };

Prefixul template<typename T> specific faptul c un template este declarat i c tipul argument T va fi folosit n declaraie Dup introducere, tipul T este utilizat ca oricare alt tip de

String template

Domeniul tipului de date T se extinde pn la finalul declaraiei prefixate de template<typename T>. Poate fi utilizat i prefixul echivalent template<class T> n ambele cazuri T este un nume de tip de date i nu numele unei clase. Utilizare: String<char> cs;
String<unsigned char> us; String<wchar_t> ws;

struct jchar { /* ... */ }; // caractere nipone String<jchar> js;

Cu excepia sintaxei speciale a numelui, obiectul String <char> cs are aceeai funcionalitate ca cea definit anterior. Fcnd String un template permite furnizarea facilitrilor implementate pentru orice tip de caracter

String template

Libraria standard ofer clas template pentru manipularea sirurilor de caractere sub numele de basic_string similar clasei templetizate prezentate n curs. n librria standard, string este un sinonim pentru basic_string<char>.
using string = std::basic_string<char>;

Astfel pentru secvena basic_string<char> sir; poate fi utilizat string sir; n general aliasurile sunt utile pentru avita denumirile lungi ale claselor generate. De asemenea se prefer a nu se cunoate detaliile despre cum un tip este definit. Un alias permite ascunderea faptului c un tip este generat dintr-un template

Definirea unui template

O clas generat dintr-un template este o clas normal. Din acest motiv utilizarea unei clase template nu implic nici un mecanism run-time comparativ cu o clas normal. Utilizarea template-urilor conduce la o descretere a codului generat deoarece codul pentru o funcie membr a unei clase template este generat dac acel membru este utilizat. nainte de a proiecta o clas template este preferabil de a proiecta, testa, depana o clas concret (String). Astfel o serie de erori de implementare pot fi eliminate n contextul exemplului concret. Pentru a putea nelege generalitatea unui template se va imagina comportarea acestuia pentru un timp concret de date. Pe scurt: o component generic este dezvoltat ca o generalizare a unui sau mai multe exemple concrete i nu pornind de la principii

Definirea unui template


Membri unei clase template sunt declarai i definii exact ca la clasele nontemplate Totui cnd un membru este declarat n afara clasei trebuie n mod explicit declaraat template-ul
template<typename T> String<T>::String() : sz{0}, ptr{ch} { ch[0] = {}; } template<typename T> String& String<T>::operator+=(T c) { // ... concaternare return this; }

Definirea unui template

Parametrul template T este un parametru i nu un nume pentru un tip specific. n domeniul String<T>, identificatorul <T> numele template-ului. Astfel numele constructorului este String<T>::String. Nu este posibil suprancrcarea numelui unei clase template.
template<typename T> class String { /* ... */ };
class String { /* ... */ }; // eroare

Un tip utilizat ca template trebuie s furnizeze interfaa ateptat de template

Instanierea unui template

Procesul de generare a unei clase ori funcii dintr-o list de argumente template este denumit adesea template instantiation. O versiune a template-ului pentru o list specific de argumente este numit specializare.
String<char> cs;
void f(void) { String<jchar> js; cs = Abcd efg hgi"; }

Pentru secvena de mai sus compilatorul genereaz declaraia claselor String<char> i String<jchar>, pentru fiecare n parte destructori i constructori cu list vid de parametri i funcia operator String<char>::operator=(char) Alte funcii membre nefiind folosite nu sunt generate.

Evident, template-urile furnizeaz o modalitate de a genera foarte mult cod din relativ mici definiii. n consecin o atenie sporit trebuie avut pentru a nu umple memoria cu definiii de funcii aproape identice.

Derivare
template<typename T> class B { /* ... */ }; template<typename T> class D : public B<T> { /* ... */ }; template<typename T> void f(B<T>); void g(B<int> pb, D<int> pd) { f(pb); // f<int>(pb) f(pd); // f<int>(static_cast<B<int>*>(pd)); // conversie standard D<int>* to B<int>* }

Sfaturi

A se utiliza template-uri pentru


a implementa algoritmi ce se adreseaz mai multor tipuri de argumente a implementa cantainere

Cele dou declaraii template<typename T> i template<class T> sunt sinonime nainte de a proiecta un template se va proiecta i implementa o versiune nontemplate. Ulterior se va generaliza parametriznd tipul/tipurile de date O funcie virtual nu poate fi o funcie template membr A se suprancrca funciile template pentru a se obine aceeai semantic pentru mai multe tipuri de argumente () A se utiliza aliasuri de template-uri pentru a simplifica notaia i a ascunde detaliile de implementare A se include definiiile template n orice fisier surs unde este necesar

V mulumesc !

S-ar putea să vă placă și