[C con Clase] vectores y clases
Steven Davidson
srd4121 en njit.edu
Jue Abr 30 22:49:24 CEST 2009
Hola Nelfi,
nelfi hernandez wrote:
> Gracias Steven por tus repuestas, pero hubo cierto error al copiar y
> pegar el codigo, la clase se llama habitantes_dn, no se como pude
> hacer borrado lo que le faltaba, pero en mi codigo fuente esta bien,
¡Qué raro! En fin, si lo tienes bien en tu código fuente, entonces bien
está.
> pido disculpas por mi error, por lo demas he acatado tus sugerencias,
> y he implemetado un constructor por defecto, lo que intento hacer si
> se puede hacer es crear un vector por ejemplo:
>
> vector<habitantes_dn> ID_objeto1
> habitantes_dn ID_objeto2
>
> y ir metiendo datos con ;
>
> ID_objeto1.push_back(ID_objeto2);
>
> Lo que no se es como poder implementar esto, sin tener que delarar
> una estructura, dentro de la clase, espero haber sido lo
> suficientemente explicito.
>
No veo que necesites crear otra estructura ni anidarla. Las sentencias
que acabas de escribir son correctas. Por ejemplo,
int main()
{
vector< habitantes_dn > lista;
lista.push_back( habitantes_dn() );
lista[0].agregar();
lista.push_back( habitantes_dn() );
lista[1].agregar();
...
return 0;
}
Lo que realmente estamos haciendo es instanciar un objeto temporal para
luego copiarlo al último elemento. Sin embargo, 'vector' funciona en
base a crear arrays dinámicos de una cantidad internamente calculada. Es
decir, 'vector' no aumenta su array interno para un solo elemento, sino
para varios. Como cada elemento es un objeto, esto significa que al
crear memoria para un objeto puede suponer la instanciación de varios
más. Por esto recomendé que definieras un constructor.
Dicho esto, también tenemos que tener en cuenta que al agregar un nuevo
objeto, estamos copiando ese objeto. Esto implica que necesitamos tener
un constructor copia. En tu caso, no es necesario definir un constructor
copia, porque el que existe por defecto nos sirve perfectamente.
El problema que veo con tu implementación de la clase 'habitantes_dn' es
que no tienes funciones miembros para acceder a los datos privados. Es
decir, deberías tener lo siguiente:
class habitantes_dn
{
private:
string nombre;
string apellido;
unsigned long cedula;
unsigned short int ano_nacimiento;
string mes_nacimiento;
unsigned short int dia_nacimiento;
unsigned short int edad;
string provincia;
string direccion;
string telefono;
float estatura;
float peso_corporal;
string color_piel;
string estado_civil;
string religion;
char puede_votar;
public:
habitantes_dn(); // Constructor de la clase
//~habitantes_dn(); // Destructor de la clase
// -- Acceso: lectura y escritura -- //
const string &Nombre() const { return nombre; }
const string &Nombre( const string &ref )
{
nombre = ref;
return nombre;
}
const string &Apellido() const { return apellido; }
const string &Apellido( const string &ref )
{
return apellido = ref;
}
unsigned long Cedula() const { return cedula; }
unsigned long Cedula( unsigned long ced )
{
if( verificar(ced) ) cedula = ced;
return cedula;
}
...
// Operaciones
void agregar();
void actualizar();
void ver();
};
Dicho esto, tengo que comentar acerca de las dos primeras funciones que
creaste a modo de operaciones. Al definir las otras funciones de acceso,
que acabo de mencionar, no necesitas 'agregar()' ni 'actualizar()' como
funciones miembros. Quizá sea una buena idea tenerlas como funciones
globales, pero no como miembros. Por ejemplo,
void agregar( habitantes_dn &obj )
{
system( "clear" );
cout << "\n\nAgrege los datos del habitante por favor..."
<< endl << endl;
cout << "Nombre : ";
getline( cin, str );
obj.nombre( str );
cout << "\n\nApellido : ";
getline( cin, str );
obj.apellido( str );
...
}
También aconsejo crear un constructor que admita instanciar un objeto
pasando los valores necesarios para describir un habitante. Por ejemplo,
class habitantes_dn
{
...
habitantes_dn( const string &nom="",
const string &ape="",
unsigned long ced=0,
unsigned short int anno=0,
const string &mes="",
unsigned short int dia=0,
... );
...
};
De esta manera, podemos instanciar un objeto directamente con toda la
información escrita explícita e implícitamente. Por ejemplo,
int main()
{
vector< habitantes_dn > lista;
lista.push_back( habitantes_dn("Nelfi","Hernandez") );
lista[0].Puede_Votar( 'S' );
lista.push_back( habitantes_dn("Salvador","Pozo") );
lista[1].Puede_Votar( 'S' );
...
return 0;
}
Aquí, instanciamos dos objetos donde explícitamente indicamos los
nombres y apellidos, pero la demás información es implícita en el
constructor. Posteriormente, accedemos a cada objeto para modificar el
valor de un dato en particular; en este caso es 'puede_votar'.
Por último, veo que algunos datos no son necesarios. Por ejemplo,
guardas la fecha de nacimiento al igual que su edad. Esto no es
necesario y de hecho puede ser peligroso. Aconsejo pedir y guardar la
fecha de nacimiento. Puedes ofrecer dar la edad, pero podemos calcularla
a partir de la fecha de nacimiento y la fecha actual.
Quizá sea mejor implementar otra clase para representar una fecha: día,
mes, y año, para luego instanciar un objeto dentro de 'habitantes_dn'.
> Gracias.
>
> PD: Lo de system("clear"); es que estoy en Linux.
>
Lo suponía, pero quería comentar este matiz.
Espero que todo esto te sirva y te oriente.
Steven
Más información sobre la lista de distribución Cconclase