Disponible la nueva versión "donationware" 7.3 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.