Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
POO - Curs Doc-1.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
868.86 Кб
Скачать

§17. Funcţii-şablon şi clase-şablon

Funcţiile-şablon sunt concepute pentru a uşura procesul de creare a unor funcţii care realizează algoritmi similari, deosebindu-se doar prin tipul datelor prelucrate.

Să considerăm următorul exemplu. Să se realizeze două funcţii: una permite găsirea elementului maximal al unui tablou de numere întregi, iar alta permite găsirea elementului maximal al unui tablou de numere cu virgulă mobilă.

Presupunând că tabloul de numere întregi este de tip int, iar tabloul de numere cu virgulă mobilă este de tip float, sunt propuse următoarele funcţii:

  • pentru tabloul de numere întregi:

int el_max(int *tb, int n_el)

{

int max=tb[0];

for (int i=1; i< n_el ; i++)

if (max < tb[i]) max=tb[i];

return max;

}

  • pentru tabloul de numere cu virgulă mobilă:

float el_max (float *tb, int n_el)

{

float max=tb[0];

for (int i=1; i< n_el ; i++)

if (max < tb[i]) max=tb[i];

return max;

}

Din compararea acestor funcţii se poate observă că ele sunt identice prin setul de instrucţiuni utilizate şi se deosebesc doar prin tipurile unor variabile locale sau ale unor parametri fictivi. Pentru a descrie mai simplu astfel de algoritmi se utilizează funcţiile-şablon. Limbajul C++ are încorporat în el mecanismul funcţiilor-şablon. Ele se mai numesc şi funcţii parametrizate sau funcţii generice. Prin intermediul unei singure descrieri a funcţiei-şablon este realizată, de fapt, descrierea unei mulţimi de funcţii, câte una pentru diferite combinaţii de tipuri de date. O funcţie-şablon este descrisă în felul următor:

template

<class Ta1, class Ta2, . . ., class Tak>

[tip_r] nume_functie([lista_par_fictivi])

{

. . .

//instructiune

. . .

}

unde template este cuvântul-cheie; Ta1, Ta2, …, Tak sunt o serie de tipuri abstracte de date, iar celelalte elemente ale funcţiei sunt cunoscute din descrierea funcţiilor obişnuite. Tipurile abstracte de date pot fi utilizate ca descriptori pentru descrierea parametrilor fictivi sau a variabilelor locale. Tipul valorii returnate de funcţie poate fi la necesitate descris cu ajutorul unuia dintre tipurile abstracte. Revenind la exemplul precedent, în conformitate cu descrierea generală este obţinută următoarea funcţie-şablon:

template

<class Tip>

Tip el_max (Tip *tb, int n_el)

{

Tip max;

max=tb[0];

for (int i=1 ; i < n_el ; i++)

if (max < tb[i]) max =tb[i];

return max;

}

Din funcţia-şablon este obţinută funcţia reală necesară. Funcţiile reale se obţin la etapa compilării prin înlocuirea tipurilor abstracte de date prin tipuri reale de date. Un procedeu corect cere şi existenţa unui prototip care descrie funcţia reală necesară. Dacă funcţia-şablon este descrisă mai sus de locul utilizării, atunci prototipul funcţiei reale poate să lipsească. Iată forme de utilizare a funcţiei-şablon din exemplul anterior:

. . .

void main()

{

int el_max(int * , int);

float el_max(float *, int);

int ti[4]={-240,4,330,7};

float tf[3]={1.2, -3.47, 27.5};

double td[4]={0,1.12,2.45,3.27};

cout << el_max(ti, 4)<< endl;

cout << el_max(tf, 3)<< endl;

cout << el_max(td, 4)<< endl;

}

Nu totdeauna algoritmul descris de funcţia-şablon este acel care poate fi aplicat absolut pentru toate tipurile reale de date utilizate în program. Unele date de anumite tipuri pot necesita algoritmi diferiţi. În asemenea situaţii, pe lângă funcţii-şablon sunt admise şi funcţii obişnuite, care au acelaşi nume cu funcţiile-şablon şi corespund algoritmilor diferiţi. Dacă există şi funcţii-şablon şi funcţii obişnuite cu acelaşi nume, prioritare sunt funcţiile obişnuite elaborate pentru unele combinaţii de date de anumite tipuri concrete. De exemplu, suma a două variabile de tip char ar putea însemna un şir de caractere constând din valorile acestor variabile, ceea ce se deosebeşte desigur de suma a două variabile numerice. Pentru variabile numerice de tip int, short, long, float etc., este realizată o funcţie-şablon, iar pentru variabile de tip char este propusă o funcţie obişnuită, care realizează algoritmul necesar:

  • variabile numerice:

template

<class Ta>

T suma (Ta x, Ta y)

{

return (x+y);

}

  • variabile de tip char:

char* suma (char x, char y)

{

char *sir;

sir = new char[3];

sir[0] = x;

sir[1] = y;

sir[2] = ’\0’;

return sir;

}

Trebuie de subliniat faptul că funcţiile-şablon pot fi supraîncărcate tot aşa ca şi funcţiile obişnuite.

Dacă până acum au fost propuse exemple de funcţii-şablon care conţineau doar un singur tip abstract, în continuare este prezentat un exemplu conţinând mai multe tipuri abstracte.

Exemplu. De alcătuit o funcţie-şablon care permite compararea unei valori cu suma elementelor unui tablou.

template

<class Ta1, class Ta2>

int compar_suma (Ta1 *tablou, Ta2 val, int numEl)

{

int i;

Ta1 suma=0;

for(i=0; i<numEl; i++)

suma+=tablou[i];

return (val-suma);

}

Un alt mecanism ce uşurează mult procesul de proiectare şi implementare a claselor este mecanismul claselor-şablon. Clasele-şablon permit crearea unei mulţimi de clase asemănătoare după funcţionalitate care se deosebesc doar după tipul datelor prelucrate. Toate funcţiile membre ale unei clase-şablon sunt funcţii-şablon. Pentru a descrie o clasă-şablon, este utilizată următoarea schemă generală:

template

<class Ta1, class Ta2, …, class Tak>

class nume_cl_sb

{

. . .

// membri ai clasei

. . .

};

unde Ta1, Ta2, …., Tak sunt tipuri abstracte de date, care pot servi la descrierea tipurilor date-membre, a tipurilor valorilor returnate de funcţiile-membre, a tipurilor parametrilor fictivi, a tipurilor variabilelor locale ale funcţiilor membre. Pentru descrierea funcţiilor membre ale unei clase-şablon este utilizat modelul ce urmează:

template

<class Ta1, class Ta2, …, class Tak>

tip_r nume_cl_sb<Ta1, Ta2, …, Tak>::nume_fn(lista_pf)

{

. . .

//instructiuni

. . .

}

unde nume_fn este o oarecare funcţie-membră, iar lista_pf reprezintă lista parametrilor fictivi. Pentru a crea obiecte în baza unei clase-şablon, mai întâi tipurile abstracte sunt înlocuite cu tipuri concrete de date, obţinând o clasă care prelucrează date de tipuri concrete, iar apoi este aplicat în mod obişnuit constructorul clasei pentru a finaliza acţiunea:

nume_cl_sb<Tc1, Tc2, …, Tck> nume_ob(lista_pr);

unde Tc1, Tc2, …, Tck sunt tipuri concrete de date, nume_ob reprezintă numele obiectului creat, iar lista_pr este lista parametrilor reali.

Exemplu. De alcătuit un program în care este realizată clasa-şablon stiva, creând mai apoi stive concrete de diferite tipuri.

template

<class T>

class stiva

{

T *stv ; // stiva

int dim; // dimensiunea stivei

int vst; // varful stivei

public:

stiva(int d);

~stiva();

T push (T el);

T pop ( );

friend ostream & operator << (ostream & fl, stiva st);

};

//------------

template

<class T>

stiva <T> :: stiva (int d)

{

stv=new T[d];

if(stv==NULL)

dim=0;

else

dim=d;

vst=0;

}

//------------

template

<class T>

stiva <T> :: ~stiva ()

{

if(stv !=NULL)

delete [] stv;

}

//------------

template

<class T>

T stiva <T> :: push (T el)

{

if (vst<dim)

{

stv[vst]=el;

vst ++;

return el;

}

else

return –1;

}

//------------

template

<class T>

T stiva <T> :: pop ( )

{

if (vst>0)

{

vst -- ;

return stv[vst];

}

else

return –1;

}

//------------

template

<class T>

ostream & operator <<(ostream &fl, stiva <T> st)

{

for (int i=0; i<st.vst; i++)

fl << st.stv[i] << ’ ’ ;

return fl;

}

Memorând implementarea clasei în fişierul stiva_p.hpp, includem acest fişier în programul principal, efectuând o serie de operaţii cu diferite tipuri de stive:

#include <iostream.h>

#include "stiva_p.hpp"

void main ()

{

stiva<int> si(10);

stiva<long> sl(15);

stiva<float> sf(20) ;

for (int i=0; i<10; i++)

{

si.push(i);

sl.push(i+100000);

sf.push(float i/10.0);

}

cout << si << endl;

cout << sl << endl;

cout << sf << endl;

si.pop() ;

cout << si << endl ;

}

Remarcă: Stiva generică realizată este orientată la descrierea stivelor pentru tipuri numerice de date.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]