CPP_RO_9_CLASE GENERICE

9.1. No?iune de clas? generic?

9.1. No?iune de clas? generic?

Clase asemeni func?iilor generice pot ?i ele s? depind? de tipuri parametrizate.

Clasa a c?rei declarare este prefixat? cu indicarea unui sau mai multor tipuri parametrizate, care vor fi concretizate ?n locurile instan?ierei acestei clase, se nume?te clas? generic? (sau clas? ?ablon, sau clas? de tip template)

Forma general? de declarare a unei clase generice este urm?toarea:

template <class tip_1[,class tip_2 ...]>
class nume_clas? [:[mod_mo?tenire] nume_clas?_de_baz?]{

// Corpul clasei

};

Drept exemplu transform?m ?n generic? clasa vectorp din capitolul despre func?ii virtuale. De data aceasta pointerii vectorului vor indica spre elementele de tip parametrizat.

#include "iostream.h"
#include "iostream.h"
//
//  C L A S S    V E C T O R P
//
template <class T> class vectorp
{
  protected:
    T **vp; // vector de pointeri cu tipul de baz? T
    int n;  // num?rul de pointeri ?n vector
 
  public:
    vectorp(int n_init)
    {
      n = n_init;
      vp = new T* [n]; // aloc?m memoria pentru vector de
                       // n pointeri
    }
 
    ~vectorp()
    {
      for(int i=0; i<n; i++) // mai ?nt?i elimin?m
                             // obiectele indicate 
        delete vp[i];        // de c?tre pointeri din
                             // vectorul de pointeri
      delete []vp;           // apoi elimin?m ?nsu?i
                             // vectorul de pointeri
    }
 
    T* &operator[](int i)
    {
      return *(vp+i); // returneaz? referin?a la un pointer din
                      // vector
    }
 
    void sort();
 
    friend ostream& operator << (ostream &stream,
                                 const vectorp<T>& vect);
};
 
template <class T> void vectorp<T>::sort()
{
  for(int i=1; i<n; i++)
    for(int j=i; (j>0)&&(**(vp+j)<**(vp+j-1)); j--)
    { // aici schimb?m cu locurile valorile a doi pointeri din
      // vector
      T *pt = *(vp+j);
      *(vp+j) = *(vp+j-1);
      *(vp+j-1) = pt;
    }
}
 
template <class T>
ostream& operator << (ostream &stream,
                      const vectorp<T>& vect)
{ // vom afi?a obiectele indicate de c?tre pointeri din vector
  for(int i=0; i<vect.n; i++)
    stream << *vect[i] << endl;
  return stream;
}


Re?ine?i cum se descriu func?iile membre ale unei clase generice ?n afara clasei.
?n func?ia main() instan?iem clasa vectorp cu tipuri concrete.

void main()
void main()
{
  // Exemplu cu un vector de pointeri spre numere reale
  vectorp<double> vd(6); // declar?m obiectul vd utiliz?nd
                         // clasa generic? vectorp
  vd[0] = new double(7.1); // operatorul de indexare [] este
                         // supra?nc?rcat ?n clasa vectorp
 
  vd[1] = new double(2.0);
  vd[2] = new double(-3.14);
  vd[3] = new double(0.0);
  vd[4] = new double(2.5);
  vd[5] = new double(1.0);
 
  cout << "Vector de reale initial:" << endl;
  cout << vd;
 
  vd.sort();
  cout << "Vector de reale dupa sortare:" << endl;
  cout << vd << endl;
 
  // Exemplu cu un vector de pointeri spre numere intregi
  vectorp<int> vi(9);
 
  vi[0] = new int(7);
  vi[1] = new int(4);
  vi[2] = new int(1);
  vi[3] = new int(-5);
  vi[4] = new int(9);
  vi[5] = new int(3);
  vi[6] = new int(4);
  vi[7] = new int(2);
  vi[8] = new int(5);
 
  cout << "Vector de intregi initial:" << endl;
  cout << vi;
 
  vi.sort();
  cout << "Vector de intregi dupa sortare:"<< endl;
  cout << vi << endl;
}
 
 
//Acest program afi?eaz? urm?torul text:
 
Vector de reale initial:
7.1
2
-3.14
0
2.5
1
Vector de reale dupa sortare:
-3.14
0
1
2
2.5
7.1
 
Vector de intregi initial:
7
4
1
-5
9
3
4
2
5
Vector de intregi dupa sortare:
-5
1
2
3
4
4
5
7
9


Pentru a explica cum va lucra clasa generic? vectorp cu obiecte, declar?m clasa string care ne va u?ura efectuarea opera?iilor cu ?iruri de caractere. Inser?m ?nainte de func?ia main(), ?n programul precedent, urm?torul cod:

//
//
//  C L A S S    S T R I N G
//
class string
{
  protected:
    char*s;
  public:
    string(char* s_init="")
    {
      s = new char[strlen(s_init)+1];
      strcpy(s, s_init);
    }
 
    virtual ostream& print(ostream &stream=cout)
    {
      return stream << s;
    }
 
    friend ostream& operator << (ostream &stream,
                                 const string& str)
    {
       return str.print(stream);
    }
 
    int operator < (string& str2)
    {
      return strcmp(this->s, str2.s)<0;
    }
};
La ?nceputul programului ad?ugam
#include "string.h"
iar la func?ia main() ad?ug?m urm?torul cod:
  // Exemplu cu un vector de pointeri spre ?iruri
  vectorp<string> vs(10);
 
  vs[0] = new string("Red");
  vs[1] = new string("White");
  vs[2] = new string("Blue");
  vs[3] = new string("Yellow");
  vs[4] = new string("Magenta");
  vs[5] = new string("Cyan");
  vs[6] = new string("Black");
  vs[7] = new string("Green");
  vs[8] = new string("Orange");
  vs[9] = new string("Violet");
 
  cout << "Vector de siruri initial:" << endl;
  cout << vs;
 
  vs.sort();
  cout << "Vector de siruri dupa sortare:" << endl;
  cout << vs << endl;
 
//Acum programul nostru va mai afi?a: 
 
Vector de siruri initial:
Red
White
Blue
Yellow
Magenta
Cyan
Black
Green
Orange
Violet
Vector de siruri dupa sortare:
Black
Blue
Cyan
Green
Magenta
Orange
Red
Violet
White
Yellow


_________________________
Autorul: dr.conf. S. Pereteatcu

9.2. Clase generice cu mai multe tipuri parametrizate

9.2. Clase generice cu mai multe tipuri parametrizate

Dup? cum se vede din sintaxa general? de declarare, o clas? generic? poate s? depind? de mai multe tipuri parametrizate. Pentru a examina cazul de declarare a clasei generice cu mai multe tipuri parametrizate, modific?m declararea clasei vectorp din programul precedent astfel:

#include "iostream.h"
#include "string.h"
//
//  C L A S S    V E C T O R P
//
template <class T, class U> class vectorp
{
  protected:
    T **vp; // vector de pointeri cu tipul de baz? T
    U n; // num?rul de pointeri ?n vector este de tip parametrizat
 
  public:
    vectorp(U n_init)
    {
      n = n_init;
      vp = new T* [n]; // aloc?m memoria pentru vector de
                       // n pointeri
    }
 
    ~vectorp()
    {
      for(U i=0; i<n; i++) // mai ?nt?i elimin?m obiectele
                           // indicate de
        delete vp[i];      // c?tre pointeri din vectorul de
                           // pointeri
      delete []vp;         // apoi elimin?m ?nsu?i vectorul
                           // de pointeri
    }
 
    T* &operator[](U i)
    {
      return *(vp+i);  // returneaz? referin?a la un pointer
                       // din vector
    }
 
    void sort();
 
    friend ostream& operator << (ostream &stream,
                        const vectorp<T, U>& vect);
};
 
template <class T,class U> void vectorp<T,U>::sort()
{
  for(U i=1; i<n; i++)
    for(U j=i; (j>0) && (**(vp+j)<**(vp+j-1)); j--)
    { // aici schimb?m cu locurile valorile a doi pointeri din
      // vector
      T *pt = *(vp+j);
      *(vp+j) = *(vp+j-1);
      *(vp+j-1) = pt;
    }
}
 
template <class T, class U>
ostream& operator << (ostream &stream, const vectorp<T, U>& vect)
{ // vom afi?a obiectele indicate de c?tre pointeri din vector
  for(U i=0; i<vect.n; i++)
    stream << *vect[i] << endl;
  return stream;
}
Modific?m ?i func?ia main() ca ea s? se arate astfel:
void main()
{
  // Exemplu cu un vector de pointeri spre numere reale
  vectorp<double, short> vd(6); // indicii de tip
                                // signed short
  vd[0] = new double(7.1);
  vd[1] = new double(2.0);
  vd[2] = new double(-3.14);
  vd[3] = new double(0.0);
  vd[4] = new double(2.5);
  vd[5] = new double(1.0);
 
  cout << "Vector de reale initial:" << endl;
  cout << vd;
 
  vd.sort();
  cout << "Vector de reale dupa sortare:" << endl;
  cout << vd << endl;
 
  // Exemplu cu un vector de pointeri spre numere intregi
  vectorp<int, unsigned> vi(9); // indicii de tip
                                // unsigned int
  vi[0] = new int(7);
  vi[1] = new int(4);
  vi[2] = new int(1);
  vi[3] = new int(-5);
  vi[4] = new int(9);
  vi[5] = new int(3);
  vi[6] = new int(4);
  vi[7] = new int(2);
  vi[8] = new int(5);
 
  cout << "Vector de intregi initial:" << endl;
  cout << vi;
 
  vi.sort();
  cout << "Vector de intregi dupa sortare:"<< endl;
  cout << vi << endl;
 
  // Exemplu cu un vector de pointeri spre ?iruri
  vectorp<string, long> vs(10); // indicii de tip
                                // long int
  vs[0] = new string("Red");
  vs[1] = new string("White");
  vs[2] = new string("Blue");
  vs[3] = new string("Yellow");
  vs[4] = new string("Magenta");
  vs[5] = new string("Cyan");
  vs[6] = new string("Black");
  vs[7] = new string("Green");
  vs[8] = new string("Orange");
  vs[9] = new string("Violet");
 
  cout << "Vector de siruri initial:" << endl;
  cout << vs;
 
  vs.sort();
  cout << "Vector de siruri dupa sortare:" << endl;
  cout << vs << endl;
 
  char ch; 
  cin >> ch;
}


Rezultatele afi?ate de programul acesta coincid ?n ?ntregime cu cele precedente.
Mai declar?m o clas?. Clasa complex va incapsula opera?ii cu numere complexe.

//
//  C L A S S    C O M P L E X
//
class complex
{
  protected:
    double re;
    double im;
  public:
    complex(double re_init=0.0, double im_init=0.0)
    {
      re=re_init;
      im=im_init;
    }
 
    virtual ostream& print(ostream &stream=cout)
    {
      if(re!=0.0)
        stream << re;
      if(im!=0.0)
      {
        if(im<0.0)
        {
          stream << "-";
          if(im!=-1.0)
            stream << -im;
        }
        else
        {
          stream << "+";
          if(im!=1.0)
            stream << im;
        }
        stream << "i";
      }
      else
        if(re==0.0)
          stream << re;
 
      return stream;
    }
 
    friend ostream& operator << (ostream &stream,
                                 const complex& c)
    {
       return c.print(stream);
    }
 
    int operator < (complex& c2)
    {
 
      return this->re < c2.re ? 1 :
                 (this->re > c2.re ? 0 :
                     (this->im < c2.im ? 1 : 0));
    }
};


Subliniem c? ?n clasa complex, prin supra?nc?rcare a operatorului <, a fost introdus? rela?ia de ordine. Asta ne va da posibilitatea s? sort?m numere complexe ?n scop demonstrativ.

Mai inser?m ?n func?ia main() un fragment de cod:

// Exemplu cu un vector de pointeri spre numere complexe
  vectorp<complex, int> vc(7); // indicii de tip int 
 
  vc[0] = new complex(1.,2.);
  vc[1] = new complex(-2.,1.);
  vc[2] = new complex(1.,-2.);
  vc[3] = new complex(-3.,2.);
  vc[4] = new complex(1.,1.);
  vc[5] = new complex(0.,0.);
  vc[6] = new complex(0.,-3.);
 
  cout << "Vector de complexe initial:" << endl;
  cout << vc;
 
  vc.sort();
  cout << "Vector de complexe dupa sortare:" << endl;
  cout << vc << endl;
Fragmentul ad?ugat afi?eaz? urm?torul text:
Vector de complexe initial:
1+2i
-2+i
1-2i
-3+2i
1+i
0
-3i
Vector de complexe dupa sortare:
-3+2i
-2+i
-3i
0
1-2i
1+i
1+2i


Exerci?iul 9.1. Concretiza?i clasa generic?  vectorp cu tipul fractie_rationala. Crea?i un vector de pointeri spre obiecte fractie_rationala, rational_fara_semn, rational. Afi?a?i obiectele pointate de c?tre pointerii vectorului, sorta?i obiectele, afi?a?i obiectele dup? sortare.
_________________________
Autorul: dr.conf. S. Pereteatcu

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов