Constructores Adicionales
Asignación en el Cuerpo del Constructor
Las sentencias dentro del cuerpo de un constructor realizan asignaciones, no inicializaciones. La inicialización ocurre solo una vez, mientras que el cuerpo permite múltiples asignaciones:
class Fecha {
int _anio;
int _mes;
int _dia;
public:
Fecha(int anio = 2003, int mes = 12, int dia = 12) {
_anio = anio;
_mes = mes;
_dia = dia; // Asignación, no inicialización
}
};
Lista de Inicialización
Es el lugar donde los miembros se definen e inicializan. Cada variable miembro debe aparecer una sola vez:
class Fecha {
int _anio;
int _mes;
int _dia;
public:
Fecha(int anio = 2003, int mes = 12, int dia = 12)
: _anio(anio), _mes(mes), _dia(dia) {}
};
Casos obligatorois para lista de inicialización:
- Miembros
consto referencias - Tipos personalizados sin constructor por defecto
class Hora {
int _hora;
int _minuto;
public:
Hora(int h, int m) : _hora(h), _minuto(m) {}
};
class Evento {
const int _id;
Hora _hora;
public:
Evento(int id, int h, int m) : _id(id), _hora(h, m) {}
};
Detalles de Constructores
Valores predeterminados en declaraciones:
class Sensor {
int _valor = 0;
int _precision = 1;
};
Palabra Clave explicit
Evita conversiones implícitas en constructores de un parámetro:
class Intervalo {
int _minutos;
public:
explicit Intervalo(int mins) : _minutos(mins) {}
};
void prueba() {
Intervalo i1(30); // Correcto
Intervalo i2 = 30; // Error: conversión implícita deshabilitada
}
Miembros static
Concepto
Variables compartidas por todas las instancias de la clase:
class Contador {
static int instancias;
public:
Contador() { instancias++; }
static int obtener() { return instancias; }
};
int Contador::instancias = 0;
Características
- Definición externa obligatoria
- Acceso mediante nombre de clase u objeto
- Funciones estáticas carecen de puntero
this
int main() {
Contador c1, c2;
cout << Contador::obtener(); // 2
cout << c1.obtener(); // 2
}
Relaciones de Amistad
Funciones Amigas
Acceden a miembros privados sin ser métodos:
class Almacen {
int _capacidad;
friend void verCapacidad(const Almacen& a);
};
void verCapacidad(const Almacen& a) {
cout << a._capacidad;
}
Clases Amigas
Acceso bidireccional controlado:
class Motor {
int rpm;
friend class Coche;
};
class Coche {
Motor m;
public:
void ajustarRPM(int v) { m.rpm = v; }
};
Clases Internas
Clases anidadas con acceso privilegiado:
class Sistema {
static int recursos;
class Subsistema {
public:
void usar() { cout << recursos; }
};
};
int Sistema::recursos = 100;
Características:
- Acceso directo a miembros estáticos del exterior
- Sin impacto en tamaño de clase contenedora
Objetos Anónimos
Objetos temporales sin identificador:
class Temporal {
public:
~Temporal() { cout << "Destruido"; }
};
int main() {
Temporal(); // Objeto anónimo, destruido inmediatamente
}
Optimizaciones del Compilador
Ejemplo de elisión de copias:
class Ejemplo {
public:
Ejemplo() = default;
Ejemplo(const Ejemplo&) { cout << "Copia"; }
};
Ejemplo crear() {
return Ejemplo(); // Omite copia
}
int main() {
Ejemplo e = crear(); // Construcción directa
}