constructores-destructores-en-cpp

Constructores y destructores en C++

Un constructor es una función especial miembro de una clase que se invoca automáticamente cuando se crea un objeto de esa clase.

Los constructores tienen el mismo nombre que la clase y no tienen un tipo de retorno (ni siquiera void)

Su principal propósito es inicializar los miembros de la clase y realizar cualquier configuración necesaria para asegurar que los objetos comiencen en un estado válido

Sintaxis de constructores

La sintaxis básica de un constructor es simplemente el propio nombre de la clase. Por ejemplo, así podemos definir un constructor sin parámetros.

class MyClass {
public:
   MyClass() {
	   // Inicialización por defecto
   }
};

En este caso, tenemos un constructor de MyClass sin ningún parámetro.

Pero también podemos tener constructores con uno o más argumentos, que nos permite inicializar un objeto con valores proporcionados como argumentos. Por ejemplo.

class MyClass {
private:
   int x;
public:
   MyClass(int val) : x(val) {
	   // Inicialización con un valor
   }
};

En este caso, tenemos un constructor que recibe val, y usamos este valor para inicializar el miembro privado x mediante la sintaxis :x(val).

Constructor por defecto

Toda clase tiene que tener un constructor. Si no definimos un el compilador proporcionará uno automáticamente (sin parámetros ni acciones).

Sin embargo, si defines un constructor con parámetros, el constructor por defecto no se generará automáticamente.

Inicialización de Miembros

Los constructores permiten inicializar miembros de la clase utilizando una lista de inicialización. Esto es preferible a la inicialización dentro del cuerpo del constructor, especialmente para miembros constantes o referencias.

class MyClass {
private:
    int x;
    const int y;
public:
    MyClass(int a, int b) : x(a), y(b) {}
};

Sobrecarga de constructores

La sobrecarga de constructores significa que podemos tener múltiples constructores con diferentes firmas (número de parámetros y/o tipos de parámetros) y el compilador seleccionará el constructor adecuado en función de los argumentos que se pasen al crear un objeto.

La sobrecarga de constructores funciona de manera similar a la sobrecarga de funciones

#include <iostream>
using namespace std;

class Persona {
public:
    string nombre;
    int edad;

	// Constructor con un parámetro (solo nombre)
    Persona(string n) {
        nombre = n;
        edad = 0;
    }

    // Constructor con dos parámetros (nombre y edad)
    Persona(string n, int e) {
        nombre = n;
        edad = e;
    }
};

Persona p1("Luis");
Persona p2("Ana", 25);
}

En el ejemplo,

  • El primer constructor recibe el nombre y establece una edad predeterminada (0).
  • El segundo constructor recibe tanto el nombre como la edad y asigna esos valores a las propiedades del objeto.

Otros tipos de constructores

Constructor de copia

Se utiliza para crear un nuevo objeto como una copia de un objeto existente. Se genera implícitamente si no se define uno.

class MyClass {
private:
    int x;
public:
    MyClass(const MyClass& other) : x(other.x) {
        // Copia del objeto
    }
};

Constructor de Movimiento

Introducido en C++11, se utiliza para transferir recursos de un objeto a otro en lugar de copiarlos (para mejorar el rendimiento).

class MyClass {
private:
    int* data;
public:
    MyClass(MyClass&& other) noexcept : data(other.data) {
        other.data = nullptr;
    }
};

Destructores en C++

Un destructor es una función especial miembro de una clase que se invoca automáticamente cuando un objeto sale del ámbito (es decir, cuando se “destruye”).

A diferencia de los constructores, los destructores no aceptan parámetros ni devuelven valores.

Su propósito principal es liberar cualquier recurso que el objeto pueda haber adquirido durante su vida.

Sintaxis

El nombre de un destructor es el nombre de la clase precedido por un tilde (~). Por ejemplo:

class MyClass {
private:
    int* data;
public:
    MyClass(int size) : data(new int[size]) {
        // Inicialización
    }
    
    ~MyClass() {
        delete[] data; // Liberar el recurso
    }
};

En este ejemplo, el destructor libera la memoria asignada dinámicamente cuando el objeto de MyClass es destruido.