[C con Clase] Tabla del tipo de mi clase

Steven Davidson srd4121 en njit.edu
Vie Jul 30 20:07:18 CEST 2010


Hola Javi,

Javi wrote:
> Buenas.
> Estoy intentando hacer una tabla del tipo de mi clase ,pero no se
> como hacerlo. mi clase es la siguiente:

Veo algunas cosas que podemos arreglar en esta definición.

> class lugar{
> private:
> string nombre;
> string info;
> public:
> lugar(string nombre,string info){
> this->nombre=nombre;
> this->info=info;
> }

En primer lugar, aconsejo pasar estos parámetros por referencia, para no 
tener que instanciar objetos locales de la clase 'string'. Como no nos 
interesa modificar estos parámetros - su contenido - indicamos 'const'. 
Esto quedaría así:

lugar( const string &nombre, const string &info )
{
   this->nombre = nombre;
   this->info = info;
}

Para establecer estos parámetros como valores iniciales a los datos 
privados, sugiero usar la lista inicializadora del constructor. Esto es,

lugar( const string &sNombre, const string &sInfo )
: nombre(sNombre), info(sInfo)
{}

Básicamente, estamos haciendo esto:
string nombre = sNombre;
string info = sInfo;

que viene a ser lo mismo que esto:
string nombre( sNombre );
string info( sInfo );

> string getInfo ();
>     string getNombre ();
> };
> string Lugar::getInfo()
> {
>         return info;
> }
> string Lugar::getNombre(){
> 	return nombre;
> }
> 

Esto puede estar bien como está, pero sí aconsejo indicar que son 
funciones miembro constantes; esto es,

string Lugar::getInfo() const
{
   return info;
}

string Lugar::getNombre() const
{
   return nombre;
}

Así indicamos que estas funciones no tienen intención alguna de 
modificar el estado del objeto que las invoca. Dicho de otra manera, 
estas funciones prometen no modificar los datos privados del objeto de 
esta clase.

También creo que quedaría mejor retornando referencias cosntantes de los 
miembros; o sea, así:

const string & Lugar::getInfo() const
{
   return info;
}

const string & Lugar::getNombre() const
{
   return nombre;
}

Así no tenemos que instanciar nuevos objetos. Ciertamente, no podemos 
modificar lo retornado al invocar estas funciones, pero posiblemente eso 
no sea un grave problema. Siempre podemos isntanciar un objeto 
temporalmente a partir de la referencia retornada por esta función 
miembro, si nos interesa. Por ejemplo,

lugar obj( "Pablo", "programador" );
string str = obj.getNombre() + ":" + obj.getInfo();

Aquí no tenemos un problema, porque el operador + está sobrecargado para 
aceptar referencias a 'string' constantes. Este operador retornará un 
nuevo objeto instanciado.

Por otro lado, si nos interesa hacer esto:

string str = mayusculas( obj.getNombre() );

donde 'mayusculas()' acepta una referencia a 'string' para modificarla, 
entonces tendríamos que adaptar el código para que pueda funcionar 
correctamente con nuestra nueva versión de 'getNombre()'. Podríamos 
hacer esto:

string str = mayusculas( string(obj.getNombre()) );

En este caso, también podríamos haber optado por invertir la lógica:

string str( obj.getNombre() );
mayusculas( str );

> Me podeis ayudar a declarar y acceder a la una tabla del tipo lugar??

Sospecho que con "tabla" te refieres a un array bidimensional. Esto 
simplemente es,

lugar tabla[100][200];

El problema es que tal y como has definido tu clase 'lugar', el 
compilador te va a lanzar errores. Esto es porque en el momento de 
definir este array, se instancian 20.000 (100 x 200) objetos de la clase 
'lugar'. Como el constructor de 'lugar' requiere dos parámetros, y no se 
los hemos dado, el compilador se quejará porque no encuentra una versión 
del constructor sin parámetros.

Esto implica que tenemos dos soluciones principales:
1. Definimos un constructor sin parámetros para 'lugar', o
2. diseñamos otra estructura para representar una tabla, en la cual nos 
permite instanciar cada objeto con dos parámetros.

Me inclino a sugerir que implementes la primera solución. Siempre es una 
buena práctica definir un constructor sin parámetros. A veces se 
necesita tal constructor, aunque no vayamos a usarlo explícitamente. Por 
ejemplo,

class lugar
{
   ...
   lugar() {}  // constructor sin parámetros
};

Y así, podemos hacer esto:

lugar tabla[100][200];

Automáticamente, al definir 'tabla', se instancian los objetos de 
'lugar' usando su constructor sin parámetros.

La otra alternativa es usando otra estructura de datos, como por ejemplo 
una lista dinámicamente enlazada, en la cual instanciamos cada objeto 
pasando los parámetros específicos a cada uno. Por ejemplo, usando las STL:

vector< list< lugar > > tabla( 100 );  // 100 filas x 200 columnas
list< lugar > fila;

// 200 objetos para la 1ª fila
fila.push_back( lugar("Madrid","Capital") );
fila.push_back( lugar("Ciudad Real","Capital") );
fila.push_back( lugar("Toledo","Capital") );
fila.push_back( lugar("Guadalajara","Capital") );
...
tabla.push_back( fila );  // Copiamos la 1ª fila a 'vector'

// 200 objetos para la 2ª fila
fila.clear();  // vaciamos la lista
fila.push_back( lugar("Washington, DC","Capital") );
fila.push_back( lugar("Trenton","Capital") );
fila.push_back( lugar("Albany","Capital") );
fila.push_back( lugar("Filadelfia","Capital") );
...
tabla.push_back( fila );  // Copiamos la 2ª fila a 'vector'

// Así hasta terminar con 100 listas de 200 elementos de tipo 'lugar'
...

Obviamente, he sido explícito en el ejemplo, pero sospecho que 
conseguirás esta información de un fichero o del usuario o incluso generado.

La otra opción que se me acaba de ocurrir es la de crear una tabla de 
punteros a objetos de tipo 'lugar'. Esto es,

lugar *tabla[100][200];

Esto significa que deberás instanciar cada objeto apuntado. Lo más 
seguro es que adjudicarás memoria dinámicamente para cada putnero. Por 
ejemplo,

tabla[0][0] = new lugar("Madrid","Capital");
tabla[0][1] = new lugar("Ciudad Real","Capital");
tabla[0][2] = new lugar("Toledo","Capital");
tabla[0][3] = new lugar("Guadalajara","Capital");
...
tabla[1][0] = new lugar("Washington, DC","Capital");
tabla[1][1] = new lugar("Trenton","Capital");
tabla[1][2] = new lugar("Albany","Capital");
tabla[1][3] = new lugar("Filadelfia","Capital");
...

Claro está, tendrás que eliminar la memoria previamente adjudicada, 
cuando ya no necesites esa información. Esto supone otra lista de 
operaciones 'delete'.


Espero que esto te oriente.

Steven





Más información sobre la lista de distribución Cconclase