¡Nuevo!  por fin disponible la versión 5 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


Clases genéricas

Ejemplo

Se presenta una variación sintáctica de una clase genérica utilizada en un caso anterior ( Ejemplo-2). En este caso, la definición de todas las funciones-miembro se han realizado fuera del cuerpo de la clase (off-line).

Se muestra como estas funciones deben ser definidas explícitamente como funciones genéricas ( 4.12.1), y como debe utilizarse el parámetro <T> en todas las ocurrencias del identificador mVector (caso de las definiciones del operador de asignación, constructor-copia, etc).

Recordemos que si mVector es una clase genérica, el identificador mVector debe ir acompañado siempre por un tipo entre los símbolos < > (excepto dentro del cuerpo de la clase, en cuyo caso es redundante).


class Vector {             // clase auxiliar
  public: int x, y;
  Vector& operator= (const Vector& v) {
    x = v.x; y = v.y;
    return *this;
  }
  void showV() { cout << "X = " << x << "; Y = " << y << endl; }
};

template<class T> class mVector {      // definición de plantilla mVector
  int dimension;
  public:
  T* mVptr;
  mVector& operator= (const mVector&); // operador de asignación
  mVector(int);                         // constructor por defecto
  ~mVector();                           // destructor
  mVector(const mVector<T>& mv);       // constructor-copia
  T& operator[](int i) { return mVptr[i]; }
  void showmem (int);                   // función auxiliar
  void show ();                         // función auxiliar
};

// operador de asignación ======
template<class T> mVector<T>& mVector<T>::operator=(const mVector<T>& mv) {
  delete [] mVptr;
  dimension = mv.dimension;
  mVptr = new T[dimension];
  for(int i = 0; i<dimension; i++) {
    mVptr[i]= mv.mVptr[i];
  }
  return *this;
}
// Constructor por defecto ======
template<class T> mVector<T>::mVector(int n = 1) {
  dimension = n;
  mVptr = new T[dimension];
}
// Destructor ===================
template <class T> mVector<T>::~mVector() {
  delete [] mVptr;
}
// Constructor-copia ============
template <class T> mVector<T>::mVector(const mVector<T>& mv) {
  dimension = mv.dimension;
  mVptr = new T[dimension];
  for(int i = 0; i<dimension; i++) {
    mVptr[i]= mv.mVptr[i];
  }
}
// Función auxiliar =============
template <class T> void mVector<T>::showmem (int i) {
  if((i >= 0) && (i <= dimension)) mVptr[i].showV();
  else cout << "Argumento incorrecto! pruebe otra vez" << endl;
}
// Función auxiliar =============
template <class T> void mVector<T>::show () {
  cout << "Matriz de: " << dimension << " elementos." << endl;
  for (int i = 0; i<dimension; i++) {
    cout << i << "- ";
    mVptr[i].showV();
  }
}
 
void main() {              // =====================
  mVector<Vector> mV1 = mVector<Vector>(5); // M.1
  mV1[0].x = 0; mV1[0].y = 1;
  mV1[1].x = 2; mV1[1].y = 3;
  mV1[2].x = 4; mV1[2].y = 5;
  mV1[3].x = 6; mV1[3].y = 7;
  mV1[4].x = 8; mV1[4].y = 9;
  mV1.show();
  mVector<Vector> mV2 = mV1;                 // M.8
  mV2.show();
  mV1[0].x = 9;   mV1[0].y = 0;
  mV2.showmem(0);
  mV1.showmem(0);
  mVector<Vector> mV3 = mVector<Vector>(0); // M.13
  mV3.show();
  mV3 = mV1; mV3.show();
}

La salida es exactamente la misma que en el ejemplo tomado como modelo , al que nos referimos para cualquier consulta al respecto.

Comentario

Aparte de las modificaciones introducidas en la definición de la plantilla mVector, donde las definiciones de las funciones-miembro se han sacado fuera (off-line), se ha modificado ligeramente la sintaxis de las sentencias M.1 y M.13, en el sentido de que ahora contienen una invocación explícita al constructor de la clase, y puede comprobarse como cada invocación a mVector debe ir acompañado siempre por un argumento.