es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Clase singleton de C++ haciendo el constructor privado.

Intenté usar el patrón de diseño singleton haciendo que la clase sea prácticamente única mediante la creación de un constructor no público. Sin embargo, cuando lo probé, el resultado no fue el esperado. Si se crea solo una instancia, el valor debería ser el mismo para las referencias, pero aparentemente son diferentes como se muestra a continuación. ¿Qué está mal con el código?

Código:

class SortOfSingleton
{
public:
    static SortOfSingleton& getInstance();
    int value = 0;
private:
    SortOfSingleton(int value);
};

SortOfSingleton::SortOfSingleton(int value)
{
    std::cout << "Creando nueva instancia." << std::endl;
    this->value = value;
}

SortOfSingleton& SortOfSingleton::getInstance()
{
    static SortOfSingleton instance(5);
    return instance;
}


void main()
{
    auto instance1 = SortOfSingleton::getInstance();
    instance1.value = 100;
    std::cout << instance1.value << std::endl;

    auto instance2 = SortOfSingleton::getInstance();
    std::cout << instance2.value << std::endl;
}

Resultado real:

Creando nueva instancia.
100
5

Resultado esperado:

Creando nueva instancia.
100
100
Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que el constructor todavía es accesible a través del método getInstance(), lo que significa que se pueden crear múltiples instancias, lo que va en contra de la intención del patrón singleton. Para hacer cumplir por completo el patrón singleton, el constructor debería ser privado y getInstance() debería ser la única forma de crear la instancia. En el código proporcionado, el constructor está marcado como privado, pero aún es accesible a través de la declaración de instancia estática en el método getInstance().

    Para solucionar este problema, deberíamos eliminar el parámetro del constructor y pasar el value como un parámetro separado al método getInstance(). Esto asegurará que solo haya una instancia de la clase y que el value siempre sea el mismo para esa instancia. Aquí hay un fragmento de código actualizado:

    class SortOfSingleton
    {
    public:
        static SortOfSingleton& getInstance(int value);
        int getValue();
    private:
        SortOfSingleton(int value);
        int m_value;
    };
    
    SortOfSingleton& SortOfSingleton::getInstance(int value)
    {
        static SortOfSingleton instance(value);
        return instance;
    }
    
    SortOfSingleton::SortOfSingleton(int value)
    {
        std::cout << "Creando nueva instancia."<< std::endl;
        m_value = value;
    }
    
    int SortOfSingleton::getValue()
    {
        return m_value;
    }
    
    int main()
    {
        auto instance1 = SortOfSingleton::getInstance(5);
        instance1.getValue(); // devuelve 5
        instance1.getValue() = 100;
        std::cout << instance1.getValue() << std::endl; // imprime 100
    
        auto instance2 = SortOfSingleton::getInstance(10);
        std::cout << instance2.getValue() << std::endl; // imprime 5
    
        return 0;
    }
    

    En este código actualizado, el método getInstance() toma el parámetro value y lo pasa al constructor privado. El constructor inicializa la variable miembro m_value y el método getValue() la devuelve. El método getInstance() siempre devuelve la misma instancia ya que se declara como una variable estática. Ahora, la salida será:

    Creando nueva instancia.
    100
    100
    

    En resumen, solo hay una instancia de la clase y el value es el mismo para ambas referencias.

Comments are closed.