Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-is:laboratoare:09 [2020/09/29 22:57]
eduard.ciurezu [Derivarea din/de Clase Template]
— (current)
Line 1: Line 1:
-===== Laboratorul 09: Functii si Clase Template ===== 
-In cadrul acestui laborator vom aprofunda concepte de programare generica, mai exact **functiile si clasele template**. Acestea ne vor permite sa reutilizam cod deja scris in contexte cat mai variate. 
  
-Ca referinte externe, recomandam urmatorul capitol din [[https://​discourse-production.oss-cn-shanghai.aliyuncs.com/​original/​3X/​2/​3/​2380479dcb8e375425884a10da232730bbc7f88d.pdf|Absolute C++]]: 
-  * Capitolul 16 (Chapter 16: Templates, pag. 694-729) 
- 
-====== Functii Template ====== 
-<​note>​Template = Sablon</​note>​ 
-**Functiile template** sunt utilizate pentru a substitui implementari multiple pentru o functie atunci cand singura diferenta dintre acestea apare numai prin faptul ca folosim alte tipuri de date. Semnatura functiei are acelasi numar de parametri, insa tipurile de date difera. 
- 
-Spre exemplu, intr-o aplicatie exista posibilitatea de a avea nevoie de **o functie de sortare** pentru diferite tipuri de date (**int**, **double**, **char**). In loc sa scriem cate o functie **sort()** pentru fiecare tip de date, putem scrie **o singura functie template** generica care sa primeasca tipul de date ca parametru. 
- 
-**Functiile template** folosesc cuvantul **template** pentru a preciza compilatorului faptul ca este vorba de o functie speciala, iar intre **<>​** se precizeaza care sunt **tipurile generice** folosite de functie: **<​Continut>​**. 
- 
-Tipul generic **T** este specificat prin: 
-**typename T** sau **class T**. 
- 
-<​note>​Functia este **parametrizata** dupa tipurile de date generice, nu specializata pe un singur tip de date. 
- 
-**Un parametru template** este un tip special de parametru care poate sa fie folosit pentru a transmite **un tip generic** ca argument intr-o functie.</​note>​ 
- 
-Functiile template se declara astfel: 
-<code c++>​template <class tip1, ... , class tipN> 
-tip_de_date_returnat nume_functie(semnatura) { ... };</​code>​ 
-sau 
-<code c++>​template <​typename tip1, ... , typename tipN> 
-tip_de_date_returnat nume_functie(semnatura) { ... };</​code>​ 
- 
-**Exemplu:​** 
- 
-<code cpp Max.cpp> 
-#include <​iostream>​ 
-using namespace std; 
- 
-//Functie pentru maximul dintre doua numere de tip int 
-int myMax(int x, int y) { 
-    return (x > y) ? x : y; 
-} 
- 
-//Functie pentru maximul dintre doua numere de tip double 
-double myMax(double x, double y) { 
-    return (x > y) ? x : y; 
-} 
- 
-//Functie pentru maximul dintre doua date de tip char 
-char myMax(char x, char y) { 
-    return (x > y) ? x : y; 
-} 
-</​code>​ 
-Observam ca cele trei functii difera doar prin **tipul de date returnat** si prin **tipurile de date ale parametrilor**,​ astfel putem folosi o singura functie tamplate pentru generalizare si evitam scrierea a trei functii diferite. 
-<code cpp MaxTemplate.cpp>​ 
-#include <​iostream>​ 
-using namespace std; 
- 
-//Functie pentru maximul dintre doua date de tipul generalizat T 
-template <​typename T> 
-T myMax(T x, T y) { 
-    return (x > y) ? x : y; 
-} 
- 
-int main() { 
-    cout << myMax<​int>​(21,​ 10) << endl;          //apelam functia pentru tipul de date int 
-    cout << myMax<​double>​(0.07,​ 31.56) << endl;  //apelam functia pentru tipul de date double 
-    cout << myMax<​char>​('​a',​ '​x'​) << endl;       //​apelam functia pentru tipul de date char 
-    return 0; 
-} 
-</​code>​ 
- 
-<note important>​Tipul unui **parametru template** este determinat **in momentul compilarii**. 
- 
-La apelul unei **functii template** legarea se face in **mod static**. 
- 
-**NU** o sa putem avea functii virtuale template.</​note>​ 
- 
-<note tip>In afara de tipuri generice, **functiile template** pot fi parametrizate si dupa **parametri obisnuiti**,​ similari cu cei folositi in functii.</​note>​ 
- 
-<code c++> 
-//Functie template cu parametru generic si parametru de tip int 
-template <​typename T, int dim> 
-T sum(T *vect) { 
-    T s(0); 
-    for (int i = 0; i < dim; i++) { 
-        s += vect[i]; 
-    } 
-    ​ 
-    return s; 
-} 
- 
-//Utilizare 
-int main() { 
-    int n = 10; 
-    int *vect1 = new int[n]; 
-    double *vect2 = new double[n]; 
-    ​ 
-    for (int i = 0; i < n; i++) { 
-        vect1[i] = i; 
-        vect2[i] = (double) i / 2; 
-    } 
-    ​ 
-    cout << sum<int, 10>​(vect1) << endl;      //Functia este specializata pentru int, iar dim = 10 
-    cout << sum<​double,​ 10>​(vect2) << endl;   //​Functia este specializata pentru double, iar dim = 10 
-    ​ 
-    return 0; 
-} 
-</​code>​ 
- 
-<note tip>​Putem specifica un **tip default** pentru un **tip generic**, iar daca acesta nu este specificat la apelul functiei, se va folosi tipul default.</​note>​ 
- 
-<code c++> 
-//​Parametrul generic este setat default int, iar parametrul int este setat default la valoarea 10 
-template <​typename T = int, int dim = 10> 
-T sum(T *vect) { 
-    T s(0); 
-    for (int i = 0; i < dim; i++) { 
-        s += vect[i]; 
-    } 
-    ​ 
-    return s; 
-} 
-</​code>​ 
-Acum, pentru vectorul nostru **vect1** cu **10** elemente de tip **int** putem apela astfel: 
-<code c++> 
-cout << sum<>​(vect1) << endl; //Nu specificam niciun tip si vor fi folosite cele default 
-</​code>​ 
- 
-<note warning>​**Nu** toate versiunile de compilatoarele permit argumente (tipul sau valoarea) template 
-default pentru functii **(permis de la C++11 in sus)**.</​note>​ 
-====== Clase Template ====== 
-<​note>​Exista posibilitatea realizarii de **clase template** – cu **atribute template** si/sau functii membre care folosesc **atribute de tipuri generice**.</​note>​ 
- 
-Sintaxa pentru **clasele template**: 
-<code c++> 
-template <class tip1, ... , class tipN> 
-class nume_clasa { 
-    tip1 a; 
-    tip2 b; 
-    ... 
-    tipN *vect; 
-    //Alte atribute si/sau metode 
-}; 
-</​code>​ 
-sau 
-<code c++> 
-template <​typename tip1, ... , typename tipN> 
-class nume_clasa { 
-    tip1 a; 
-    tip2 b; 
-    ... 
-    tipN *vect; 
-    //Alte atribute si/sau metode 
-}; 
-</​code>​ 
-<​note>​Ca si in cazul functiilor template, se pot transmite si parametri care nu sunt tipuri de date intre **<>​** sau **tipuri template default**.</​note>​ 
- 
-**Exemplu:​** 
-<code c++ TemplateClass.cpp>​ 
-#include <​iostream>​ 
-using namespace std; 
- 
-//Clasa template 
-template <class T> 
-class myPair { 
-    private: 
-        T a, b;    //Atribute de tip T 
-    public: 
-        myPair(T first, T second) { a = first; b = second; }    //​Constructor cu parametrii 
-        T getMax(); ​   //Functie template 
-}; 
- 
-template <class T> 
-T myPair<​T>::​getMax() { 
-    return (a > b) ? a : b; 
-} 
- 
-int main () { 
-  myPair<​int>​ Obj(100, 75); 
-  cout << Obj.getMax() << endl;    //Se va afisa 100 
-  return 0; 
-} 
-</​code>​ 
- 
-<​note>​ 
-**Functiile template** sunt un exemplu de **polimorfism la compilare** (compile time polymorphism) ca si supradefinirea functiilor. 
- 
-Fiecare apel specializat al unei functii/​clase template conduce la compilare la generarea **cate unei instante pentru fiecare specializare**. 
- 
-Daca o functie/​clasa template contine o **variabila locala statica/​atribut static** – fiecare instantiere a clasei template va contine **copia proprie a variabilei/​atributului static**. 
-</​note>​ 
- 
-====== Derivarea din/de Clase Template ====== 
- 
-**Modele de derivare simpla:** 
-  * O clasa **obisnuita** derivata dintr-o clasa **template** 
-  * O clasa **template** derivata dintr-o clasa **obisnuita** de baza 
-  * O clasa **template** derivata dintr-o alta clasa **template** 
- 
-<​note>​ 
-**O clasa template** este un sablon pentru o clasa, ea va fi instantiata in functie de tipurile de date pe care le foloseste. 
- 
-**O instantiere** conduce la **specializarea** acelei clase. 
- 
-Procesul se numeste **instantiere**,​ iar rezulatul se numeste **specializare**. 
-</​note>​ 
- 
-=== Clasa obisnuita derivata din specializarea unei clase template === 
-<code c++> 
-template <​typename T> 
-class Baza { 
-    protected: 
-        T a; 
-    public: 
-        Baza(T i) { a = i; } 
-        ... 
-}; 
- 
-class Derivata:​public Baza<​int>​ { 
-    private: 
-        int b; 
-    public: 
-        Derivata(int i, int j):Baza(i) { b = j; } 
-        ... 
-}; 
-</​code>​ 
-<note tip>​Clasa derivata o sa mosteneasca atributul **a** de tip **int** din specializarea clasei template de baza. 
- 
-Clasa derivata **NU** o sa fie clasa template.</​note>​ 
- 
-=== Clasa obisnuita derivata dintr-o clasa template nespecializata === 
-<code c++> 
-template <​typename T> 
-class Baza { 
-    protected: 
-        T a; 
-    public: 
-        Baza(T i) { a = i; } 
-        ... 
-}; 
- 
-template <​typename T> 
-class Derivata:​public Baza<​T>​ { 
-    private: 
-        int b; 
-    public: 
-        Derivata(T i, int j):​Baza<​T>​(i) { b = j; } 
-        ... 
-}; 
-</​code>​ 
-<note tip>​Clasa derivata o sa mosteneasca atributul **a** de tip **generic T** din clasa template de baza. 
- 
-La randul ei, clasa derivata o sa fie tot o **clasa template**.</​note>​ 
- 
-=== Clasa template derivata dintr-o clasa de baza neparametrizata === 
-<code c++> 
-class Baza { 
-    protected: 
-        int a; 
-    public: 
-        Baza(int i) { a = i; } 
-        ... 
-}; 
- 
-template <​typename T> 
-class Derivata:​public Baza { 
-    private: 
-        T b; 
-    public: 
-        Derivata(int i, T j):Baza(i) { b = j; } 
-        ... 
-}; 
-</​code>​ 
-<note tip>​Clasa derivata o sa mosteneasca atributul **a** de tip **int** din clasa de baza, in mod firesc. 
- 
-Clasa derivata o sa fie o **clasa template**, deoarece aceasta are atributul **b** de tip **generic T**.</​note>​ 
- 
-=== Clasa template derivata dintr-o alta clasa template === 
-<code c++> 
-template <​typename T> 
-class Baza { 
-    protected: 
-        T a; 
-    public: 
-        Baza(T i) { a = i; } 
-        ... 
-}; 
- 
-template <​typename X, typename T> 
-class Derivata:​public Baza<​T>​ { 
-    private: 
-        X b; 
-    public: 
-        Derivata(T i, X j):​Baza<​T>​(i) { b = j; } 
-        ... 
-}; 
-</​code>​ 
-<note tip>​Clasa derivata o sa mosteneasca atributul **a** de tip **generic T** din clasa template de baza. 
- 
-La randul ei, clasa derivata o sa fie tot o **clasa template**, avand inca un atribut **b** de tip **generic X**.</​note>​ 
- 
-<note important>​Cand derivam trebuie sa ne punem problema ce urmeaza sa mostenim in clasa derivata: 
-  * o clasa template: **ceva_ce_foloseste<​T>​** 
-  * specializarea clasei template: **ceva_ce_foloseste<​int>​** 
-</​note>​ 
poo-is/laboratoare/09.1601409433.txt.gz · Last modified: 2020/09/29 22:57 by eduard.ciurezu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0