Diario
de un programador. Día 182
Constructores en C++
Al
igual que en Java, en C++ también se pueden utilizar constructores.
Un
constructor es un tipo de función que tiene por finalidad inicializar los
objetos o variables con algún valor válido, para evitar que estos se
inicialicen con su valor predeterminado, todo esto con la finalidad de
evitar algún posible error.
Un
constructor debe definirse con el mismo nombre que su clase, no devuelven
ningún tipo de valor (ni siquiera void) y por lo general se declaran como
public.
Si
una clase no incluye un constructor, el compilador en forma interna crea uno
con valores predeterminados.
El
código estudiado en el capítulo 75 (tutorial anterior de c++), no posee un
constructor y a pesar de que ese
programa funciona, las buenas prácticas de programación (según lo que leí en la
web) indican que siempre se debe crear un constructor. El código mostrado en
esa oportunidad, es el siguiente:
#include<iostream>
#include<string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::getline;
class Antecedentes{
private:
string
nombre;
int edad;
public:
void
setNombre(string nom){
nombre =
nom;
}
void
setEdad(int ed){
edad =
ed;
}
string
getNombre(){
return
nombre;
}
int
getEdad(){
return
edad;
}
void
informe(){
cout
<< "Nombre: " << getNombre() << endl;
cout
<< "Edad: " << getEdad() << endl;
}
};
int main(void){
string nombreUsuario;
int edadUsuario;
Antecedentes datos;
cout << "Ingresa tu nombre:
";
getline(cin, nombreUsuario);
cout << "Ingresa tu edad:
";
cin >> edadUsuario;
datos.setNombre(nombreUsuario);
datos.setEdad(edadUsuario);
datos.informe();
return
0;
}
Este código, lo que hace es solicitar
un nombre y una edad, para luego imprimirlo en pantalla. Si a este código le
agregamos un constructor, quedaría así:
#include<iostream>
#include<string>
using
std::cout;
using
std::cin;
using
std::endl;
using
std::string;
using
std::getline;
class
Antecedentes{
private:
string nombre;
int edad;
public:
Antecedentes(){//constructor
nombre = "";
edad = 0;
}
void setNombre(string nom){
nombre = nom;
}
void setEdad(int ed){
edad = ed;
}
string getNombre(){
return nombre;
}
int getEdad(){
return edad;
}
void informe(){
cout << "Nombre: "
<< getNombre() << endl;
cout << "Edad: " <<
getEdad() << endl;
}
};
int
main(void){
string nombreUsuario;
int edadUsuario;
Antecedentes datos;
cout << "Ingresa tu nombre: ";
getline(cin, nombreUsuario);
cout << "Ingresa tu edad: ";
cin >> edadUsuario;
datos.setNombre(nombreUsuario);
datos.setEdad(edadUsuario);
datos.informe();
return 0;
}
He destacado el
código correspondiente al constructor:
Antecedentes(){//constructor
nombre = "";
edad = 0;
}
Como
se puede apreciar, este constructor tiene el mismo nombre de su clase, no tiene
un valor de retorno y su tarea en este caso es inicializar un par de variables.
La variable nombre la inicializó con unas comillas dobles, mientras que la
variable edad fue inicializada a cero. De esta forma, cada variable queda
inicializada.
Para
inicializar un objeto, hay que agregar ciertos parámetros. A continuación un
ejemplo, utilizando el mismo código anterior, pero agregando algunos
parámetros.
#include<iostream>
#include<string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::getline;
class Antecedentes{
private:
string nombre;
int edad;
public:
Antecedentes(string nombre, int
edad){ //constructor
setNombre(nombre); //llama a
la funcion set para inicializar el nombre
setEdad(edad); //llama a
la funcion set para inicializar la edad
}
void setNombre(string nom){
nombre = nom;
}
void setEdad(int ed){
edad = ed;
}
string getNombre(){
return nombre;
}
int getEdad(){
return edad;
}
};
int main(void){
Antecedentes datos("Gus", 36);
cout << "Nombre: " <<
datos.getNombre() << endl;
cout << "Edad:
" << datos.getEdad() << endl;
return 0;
}
En este caso el
constructor recibe dos argumentos, uno de tipo string y uno de tipo int
Antecedentes(string
nombre, int edad){ //constructor
En este caso necesita
de estos dos parámetros, debido a que en este constructor se van a inicializar
dos variables locales, correspondiente a las funciones setNombre y setEdad.
setNombre(nombre); //llama a la funcion set para
inicializar el nombre
setEdad(edad); //llama a la funcion set para
inicializar la edad
Posteriormente, al
crear un nuevo objeto, este debe llevar como argumento los datos que se
utilizarán para inicializar las variables de las funciones setNombre y setEdad.
Antecedentes datos("Gus", 36);
Las últimas dos líneas realizan una llamada
implícita al constructor inicializando los objetos.
cout << "Nombre: " <<
datos.getNombre() << endl;
cout << "Edad: " <<
datos.getEdad() << endl;
Hay que tener en
cuenta que cualquier constructor que no lleve argumentos, se le conoce como
constructor predeterminado
Recordar siempre
proporcionar un constructor para asegurar que los miembros de datos de las
clases se inicialicen con valores significativos.
Es una buena práctica
asegurarse que un objeto se inicialice antes que el código invoque a las
funciones.
Esto es todo por
ahora. Saludos
Gustavo J. Cerda Nilo
Septiembre 2016, Octubre 2016