Constructores y destructores
En C++, la creación, uso y destrucción de objetos se gestionan mediante constructores y destructores.
Constructores
Un constructor es una función especial cuyo nombre coincide con el de la clase y que no tiene tipo de retorno. Se ejecuta automáticamente al crear un objeto.
Tipos:
- Constructor por defecto: no recibe argumentos.
- Constructor parametrizado: recibe valores para inicializar atributos.
- Constructor delegante: llama a otro constructor de la misma clase (se verá más adelante).
- Constructores especiales: como el de copia y el de movimiento (se estudiarán más adelante).
Aunque lo estudiaremos en profundidad en el siguiente apartado, hay que indicar que en C++ moderno, se recomienda usar listas de inicialización uniforme ({}) para inicializar los atributos:
#include <iostream>
class Punto {
private:
int x;
int y;
public:
// Constructor por defecto con lista de inicialización
Punto() : x{0}, y{0} {}
// Constructor parametrizado con lista de inicialización
Punto(int valorX, int valorY) : x{valorX}, y{valorY} {}
// Método constante para mostrar el estado del objeto
void mostrar() const {
std::cout << "Punto(" << x << ", " << y << ")\n";
}
};
int main() {
Punto p1; // Se usa el constructor por defecto
Punto p2{3, 4}; // Se usa el constructor parametrizado
p1.mostrar(); // Punto(0, 0)
p2.mostrar(); // Punto(3, 4)
return 0;
}
Este programa demuestra que:
- El constructor por defecto inicializa
xeyen0. - El constructor parametrizado usa la lista de inicialización para asignar directamente los valores recibidos.
- El método
mostrar()es const porque no modifica el estado del objeto.
Destructor
Un destructor es una función especial que se ejecuta automáticamente cuando un objeto:
- sale de su ámbito,
- se elimina con
delete, - o es destruido dentro de un contenedor de la STL, por ejemplo, en un vector (
std::vector).
Su sintaxis es: ~NombreDeClase();
Ejemplo:
#include <iostream>
class Ejemplo {
private:
std::string nombre;
public:
// Constructor: se ejecuta al crear el objeto
Ejemplo(const std::string& n) : nombre{n} {
std::cout << "Constructor: " << nombre << " creado.\n";
}
// Destructor: se ejecuta automáticamente al destruir el objeto
~Ejemplo() {
std::cout << "Destructor: " << nombre << " destruido.\n";
}
};
int main() {
std::cout << "Inicio del programa.\n";
Ejemplo a("Objeto A"); // Se construye automáticamente
{
Ejemplo b("Objeto B"); // Se construye dentro de un bloque
std::cout << "Dentro del bloque.\n";
} // b sale de ámbito: se invoca su destructor aquí
std::cout << "Fin del programa.\n";
return 0; // Al finalizar main, se destruye 'a'
}
- El constructor se llama cuando se crea el objeto (
Ejemplo a("Objeto A");). - El destructor (
~Ejemplo) se ejecuta automáticamente cuando el objeto sale de su ámbito. - El orden de destrucción es inverso al de creación: el último objeto creado es el primero en destruirse.
- No es necesario invocar el destructor manualmente; el compilador lo hace por ti.
- Si no se define, el compilador genera uno por defecto.
Uso de =default y =delete
En C++ moderno, el programador puede indicar al compilador si ciertas funciones especiales (como constructores, destructores u operadores) deben generarse automáticamente o prohibirse explícitamente.
Estas dos expresiones permiten controlar el comportamiento por defecto de las clases:
=default: solicita que el compilador genere automáticamente la función.=delete: prohíbe que esa función se use.
Veamos un ejemplo:
#include <iostream>
#include <string>
class Archivo {
private:
std::string nombre;
public:
// Constructor por defecto: generado automáticamente
Archivo() = default;
// Constructor con parámetro
Archivo(const std::string& n) : nombre{n} {}
// Destructor automático
~Archivo() = default;
// Método para mostrar información
void mostrar() const {
std::cout << "Archivo: " << nombre << '\n';
}
// Ejemplo: prohibimos la creación de objetos con un número
Archivo(int) = delete;
};
int main() {
Archivo a1("datos.txt"); // OK
a1.mostrar();
Archivo a2; // OK: usa el constructor por defecto
// Archivo a3(42); // Error: constructor eliminado (=delete)
return 0;
}
=defaultle indica al compilador que genere automáticamente el constructor por defecto y el destructor.=deleteimpide que se utilice una función concreta (en este caso, el constructor que recibe un número).- Si el programador intenta usar una función eliminada, el compilador emitirá un error en tiempo de compilación.