Menu
Coddy logo textTech

Métodos y variables estáticos

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 31 de 104.

Has aprendido que los miembros estáticos se comparten entre todos los objetos. Ahora exploremos cómo definir y utilizar correctamente métodos estáticos junto con variables estáticas.

Las variables estáticas declaradas dentro de una clase deben ser definidas fuera de la clase, normalmente en un archivo de código fuente. Esto se debe a que los miembros estáticos necesitan exactamente una ubicación de almacenamiento compartida por todos los objetos:

class Counter {
    static int count;    // Solo declaración
    
public:
    Counter() { count++; }
    ~Counter() { count--; }
    
    static int getCount() {    // Método estático
        return count;
    }
};

// Definición - requerida fuera de la clase
int Counter::count = 0;

Un método estático pertenece a la clase, no a ningún objeto. Esto tiene una consecuencia importante: los métodos estáticos no pueden acceder a los miembros de instancia ni usar el puntero this, porque no se llaman sobre ningún objeto específico.

class MathUtils {
    static double pi;
    
public:
    static double circleArea(double radius) {
        return pi * radius * radius;    // Puede acceder a miembros estáticos
    }
};

double MathUtils::pi = 3.14159;

// Llamado sin un objeto
double area = MathUtils::circleArea(5.0);

Los métodos estáticos son ideales para funciones de utilidad que no necesitan el estado del objeto, métodos de fábrica que crean objetos o para acceder a datos estáticos. Dado que no requieren una instancia de objeto, se llaman utilizando el nombre de la clase y el operador de resolución de ámbito: ClassName::methodName().

challenge icon

Desafío

Fácil

Construyamos un sistema generador de IDs únicos que demuestre cómo los métodos y variables estáticos trabajan juntos para proporcionar funcionalidad a nivel de clase sin necesidad de instancias de objetos.

Crearás dos archivos para organizar tu código:

  • IDGenerator.h: Define una clase IDGenerator que genere IDs únicos secuenciales. Tu clase debe tener:
    • Un miembro estático privado nextId que rastree el siguiente ID a asignar (comienza en 1000)
    • Un miembro estático privado prefix (string) que almacene un prefijo personalizable para todos los IDs
    • Un método estático setPrefix(const std::string& p) que cambie el prefijo
    • Un método estático getNextId() que devuelva un string combinando el prefijo y el número de ID actual, y luego incremente nextId para la siguiente llamada
    • Un método estático peekNextId() que devuelva cuál sería el siguiente ID sin incrementar el contador
    • Un método estático getGeneratedCount() que devuelva cuántos IDs se han generado (pista: calcúlalo a partir del valor inicial y el nextId actual)
    • Un método estático reset() que restablezca nextId a 1000

    Recuerda definir tus miembros estáticos fuera de la clase después de la definición de la clase. Inicializa prefix a "ID-".

  • main.cpp: Demuestra la llamada a métodos estáticos utilizando el nombre de la clase sin crear ningún objeto. Lee un prefijo personalizado de la entrada, luego:

    • Imprime "Peek: <peeked_id>" usando peekNextId()
    • Genera tres IDs usando getNextId() e imprime cada uno como "Generated: <id>"
    • Imprime "Count: <count>" mostrando cuántos IDs se han generado
    • Cambia el prefijo usando el valor de entrada con setPrefix()
    • Genera dos IDs más e imprime cada uno como "Generated: <id>"
    • Imprime "Count: <count>" de nuevo
    • Llama a reset()
    • Imprime "After reset - Peek: <peeked_id>"
    • Imprime "After reset - Count: <count>"

Observa que nunca creas un objeto IDGenerator; todos los métodos se llaman directamente en la clase usando IDGenerator::methodName(). Esta es la característica clave de los métodos estáticos: pertenecen a la clase misma, no a ninguna instancia en particular.

Incluye <string> e <iostream> en tu archivo de cabecera, y no olvides las guardas de cabecera (header guards).

Hoja de referencia

Las variables estáticas declaradas dentro de una clase deben ser definidas fuera de la clase. Los miembros estáticos necesitan exactamente una ubicación de almacenamiento compartida por todos los objetos:

class Counter {
    static int count;    // Solo declaración
    
public:
    Counter() { count++; }
    
    static int getCount() {
        return count;
    }
};

// Definición - requerida fuera de la clase
int Counter::count = 0;

Un método estático pertenece a la clase, no a ningún objeto. Los métodos estáticos no pueden acceder a miembros de instancia ni usar el puntero this porque no se llaman sobre ningún objeto específico:

class MathUtils {
    static double pi;
    
public:
    static double circleArea(double radius) {
        return pi * radius * radius;    // Puede acceder a miembros estáticos
    }
};

double MathUtils::pi = 3.14159;

// Llamado sin un objeto usando el nombre de la clase
double area = MathUtils::circleArea(5.0);

Los métodos estáticos se llaman utilizando el nombre de la clase y el operador de resolución de ámbito: ClassName::methodName(). Son ideales para funciones de utilidad que no necesitan el estado del objeto, métodos de fábrica o para acceder a datos estáticos.

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "IDGenerator.h"

using namespace std;

int main() {
    // Lee el prefijo personalizado de la entrada
    string customPrefix;
    cin >> customPrefix;
    
    // TODO: Imprime "Peek: <peeked_id>" usando peekNextId()
    
    // TODO: Genera tres IDs usando getNextId() e imprime cada uno como "Generated: <id>"
    
    // TODO: Imprime "Count: <count>" mostrando cuántos IDs se han generado
    
    // TODO: Cambia el prefijo usando el valor de entrada con setPrefix()
    
    // TODO: Genera dos IDs más e imprime cada uno como "Generated: <id>"
    
    // TODO: Imprime "Count: <count>" de nuevo
    
    // TODO: Llama a reset()
    
    // TODO: Imprime "After reset - Peek: <peeked_id>"
    
    // TODO: Imprime "After reset - Count: <count>"
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos