Matrices estáticas de objetos.

En C++ se puede crear una matriz estática de objetos de múltiples formas, en función de las necesidades del programa. Una matriz estática es aquella en la cuál se conocen sus dimensiones en tiempo de compilación, y cuyas dimensiones no cambiarán durante toda la vida (ejecución) del programa. Las distintas posibilidades de creación de una matriz estática de objetos son:

  • Usando un constructor sin argumentos
  • Dando parámetros de inicialización
  • Usando un constructor con argumentos por defecto
  • Creando una matriz estática de punteros a objeto

Sunpongamos que se tiene la clase Point3D, la cual no es mas que un wrapper de tres enteros que representan un punto en un espacio euclídeo tridimensional. Observe que esta clase está dotada de un constructor sin argumentos:

class Point3D{
		int x;
		int y;
		int z;
	public:
		Point3D(){ x=y=z=0; };
		Point3D(int cx,int cy,int cz){ x=cx; y=cy; z=cz; };
		int getX(){return x;}
		int getY(){return y;}
		int getZ(){return z;}
		void setX(int cx){x=cx;};
		void setY(int cy){y=cy;};
		void setZ(int cz){z=cz;};
		friend ostream& operator<<(ostream &stream,const Point3D &point);
};

Para los ejemplos de creación de matrices se han definido las constantes FIL y COL.

#define FIL 2
#define COL 3

Usando un constructor sin argumentos

Esta es la forma mas sencilla de crear una matriz de objetos. Implica la utilización de un constructor sin argumentos o constructor por defecto. Recuerde que si en la clase define un constructor con argumentos (como en este caso), entonces se verá obligado a definir explícitamente un constructor sin argumentos, tal y como se pude observar en el código de la clase Point3D.

Pros: Es muy sencillo e intuitivo definir una matriz de objetos de esta forma.

Contras: Todos los objetos se inicializarán con los mismos valores, y seguramente se requiera de una iteración sobre la matriz para parametrizar cada objeto. Esto supone la creación de métodos set[NombreAtributo] en el cuerpo de la clase y de un segundo bucle (mayor tiempo de ejecución) para recorrer la matriz.

//Ejemplo de creación de una matriz de objetos, usando un constructor sin argumentos...
int main()
{
    int i,j;
    
    Point3D puntos[FIL][COL];
    //Imprimo los puntos
    for( i=0; i< FIL; i++){
      for(j=0; j< COL ; j++){
		cout << "punto[" << i << "][" << j << "] -> " << puntos[i][j];
      }
      cout << endl;
    }
 
    return 0;
}

Dando parámetros de inicialización

Es otra forma sencilla de crear una matriz de objetos. Para ello hay que definir un constructor con argumentos en la clase, y llamar al constructor en la creación de los objetos. Recuerde que en C++ un sentencia de definición de variables de tipo objeto, es una sentencia de acción, y que por tanto se llama al constructor de la clase.

Pros: Es sencillo definir una matriz de objetos llamando a un constructor con parámetros y cada objeto queda perfectamente inicializado con unos parámetros específicos y listo para ser usado.

Contras: Si el constructor parametrizado tiene muchos parámetros, o la matriz de objetos tiene muchos elementos, esta forma de proceder puede resultar bastante tediosa. Además esta forma implica que se conocen en tiempo de compilación los parámetros de inicio de cada objeto, cosa que muy rara vez sucede en la práctica.

//Ejemplo de creación de una matriz de objetos usando parámetros de inicialización.
int main()
{
    int i,j;
    
    Point3D puntos[FIL][COL]= {Point3D(0,0,0),Point3D(1,1,1),Point3D(2,2,2),
								Point3D(3,3,3),Point3D(4,4,4),Point3D(5,5,5)};
	
    //Imprimo los puntos
    for( i=0; i< FIL; i++){
      for(j=0; j< COL ; j++){
		cout << "punto[" << i << "][" << j << "] -> " << puntos[i][j];
      }
      cout << endl;
    }
 
    return 0;
}

Usando un constructor con argumentos por defecto

Esta forma es una mezcla de las dos anteriores. Para ello hay que definir un constructor con argumentos en la clase, y que ademas para algún argumento se definan argumentos por defecto. De esta forma se permite al programador especificar únicamente los parámetros que se consideren oportunos. Para ello se va a modificar la clase Point3D para que contenga un único constructor parametrizado, tal y como sigue a continuación:

class Point3D{
		int x;
		int y;
		int z;
	public:
		//Point3D(){ x=y=z=0; };
		//Point3D(int cx,int cy,int cz){ x=cx; y=cy; z=cz; };
		Point3D(int cx=1,int cy=1,int cz=1){ x=cx; y=cy; z=cz; };
		int getX(){return x;}
		int getY(){return y;}
		int getZ(){return z;}
		void setX(int cx){x=cx;};
		void setY(int cy){y=cy;};
		void setZ(int cz){z=cz;};
		friend ostream& operator<<(ostream &stream,const Point3D &point);
};

Se ha especificado como valor por defecto 1 para todos los argumentos para los cuales no se especifique parámetro formal en tiempo de ejecución. Recuerde que en C++ una vez se define en un método un valor por defecto para un parámetro, deberán definirse valores por defecto para todos los parámetros situados a la derecha de este. Esta regla es extensible a las llamadas al método. En una llamada a un método con parámetros por defecto, una vez se aplique el valor por defecto a un argumento, se aplicarán el resto de valores por defecto a todos los argumentos situado a la derecha de este.

Pros: Es una forma de abreviar la creación de objetos llamando a constructores parametrizados siempre que haya muchos objetos que tomen los valores por defecto. Cada objeto queda perfectamente inicializado con unos parámetros específicos y listo para ser usado.

Contras: A primera vista es una forma algo mas barroca de crear objetos. Además esta forma implica que se conocen en tiempo de compilación los parámetros de inicio de cada objeto, cosa que muy rara vez sucede en la práctica.

//Ejemplo de creación de una matriz de objetos usando un constructor con parámetros por defecto.
int main()
{
    int i,j;
    
    Point3D puntos[FIL][COL]= {Point3D(0,0,0),Point3D(),Point3D(2,2),
							Point3D(3),Point3D(4,4,4),Point3D(5,5,5)};
	
    //Imprimo los puntos
    for( i=0; i< FIL; i++){
      for(j=0; j< COL ; j++){
		cout << "punto[" << i << "][" << j << "] -> " << puntos[i][j];
      }
      cout << endl;
    }
 
    return 0;
}

Por si queda alguna duda, esta es la salida por pantalla que genera el programa en este caso:

punto[0][0] ->  x= 0 y= 0 z= 0
punto[0][1] ->  x= 1 y= 1 z= 1
punto[0][2] ->  x= 2 y= 2 z= 1

punto[1][0] ->  x= 3 y= 1 z= 1
punto[1][1] ->  x= 4 y= 4 z= 4
punto[1][2] ->  x= 5 y= 5 z= 5

Creando una matriz estática de punteros a objeto

Es una forma quizás mas rebuscada de crear una matriz de objetos. Para ello hay que definir una matriz estática de punteros a objeto. Esto no crea los objetos, solamente crea los punteros, posteriormente hay que crear los objetos y hacer que cada puntero apunte a su objeto correspondiente.

Pros: Es sencillo definir una matriz de punteros a objeto. Posteriormente al crear cada objeto se puede parametrizar de forma libre, sin estar sujetos a especificar los parámetros en tiempo de compilación, por ejemplo se podrían leer de un archivo.

Contras: El número de objetos será fijo, ya que la matriz de punteros a objeto es estática, por tanto se debe conocer el número de objetos a crear en tiempo de compilación. Se necesita un bucle para recorrer la matriz de punteros e ir conectando cada puntero con la dirección de memoria dinámica reservada para el objeto correspondiente. Al terminar el programa se deberá recorrer de nuevo la matriz de punteros para liberar la memoria dinámica que fue reservada para cada objeto. Es una buena práctica poner como valor del puntero NULL una vez se ha liberado la memoria a la que apuntaba.

//Ejemplo de creación de una matriz de objetos usando una matriz estática de punteros a objeto
int main()
{
	int i,j;

	//Creo la matriz de punteros
	Point3D* puntos[FIL][COL];

	//Creo los objetos punto y hago que cada puntero apunte a un objeto
	for( i=0; i< FIL; i++)
		for(j=0; j< COL ; j++)
		puntos[i][j] = new Point3D(i,j,i+j);

	//Imprimo los puntos
	for( i=0; i< FIL; i++){
		for(j=0; j< COL ; j++){
			cout << "punto[" << i << "][" << j << "] -> " << *puntos[i][j];
		}
		cout << endl;
	}

	//Libero la memoria correspondiente a cada objeto
	for( i=0; i< FIL; i++)
		for(j=0; j< COL ; j++){
			delete puntos[i][j];
			puntos[i][j]=NULL;
		}


	return 0;
}

Observe que ahora para imprimir cada objeto de tipo Point3D se debe utilizar el operador de indirección *, ya que en la matriz se manejan punteros a objeto, en lugar de objetos. A continuación se muestra la salida por pantalla generada por el programa en este caso:

punto[0][0] ->  x= 0 y= 0 z= 0
punto[0][1] ->  x= 0 y= 1 z= 1
punto[0][2] ->  x= 0 y= 2 z= 2

punto[1][0] ->  x= 1 y= 0 z= 2
punto[1][1] ->  x= 1 y= 1 z= 3
punto[1][2] ->  x= 1 y= 2 z= 4

Descargas Disponibles:

Acerca de franciscoguemes

Ingeniero en Informática
Esta entrada fue publicada en C/C++. Guarda el enlace permanente.

Una respuesta a Matrices estáticas de objetos.

  1. Pingback: Matrices dinámicas de objetos. | Francisco José Güemes Sevilla

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s