Pregunta

Digamos que tengo una clase:

class NumberCollection
{
public:
    typedef std::set<int> SetType;
    typedef SetType::iterator iterator;
    void insert(int n);

    iterator begin();
    iterator end();
    size_t size() const;

    iterator difficultBegin();
    iterator difficultEnd();
    size_t difficultSize() const;    

private:
    SetType easySet_, difficultSet_;
}

Cuando insert() añade un elemento a easySet_. miembros de difficultSet_ cambian en función de los miembros de easySet_.

El problema que estoy teniendo es que, inserciones múltiples significa que difficultSet_ se recalcula de manera constante. Así que quiero difficultSet_ a ser calculado con pereza (es decir, sólo cuando difficultBegin(), difficultEnd() o difficultSize() se llaman). El problema es, entonces yo realmente tienen que hacer en un difficultSet_ mutable porque de lo contrario difficultSize() no puede operar en él.

Así que ahora mi declaración de la clase parece

class NumberCollection
{
public:
    typedef std::set<int> SetType;
    typedef SetType::iterator iterator;
    void insert(int n);

    iterator begin();
    iterator end();
    size_t size() const;

    iterator difficultBegin();
    iterator difficultEnd();
    size_t difficultSize() const;    

private:
    SetType easySet_; 
    mutable SetType difficultSet_;
    mutable bool upToDate_;
}

Siento que este es un mal diseño sin embargo. ¿Hay una mejor manera?

¿Fue útil?

Solución

Eso es totalmente la manera de hacerlo. Const const puede significar binario, o puede significar const conceptualmente. Usando mutable significa que está haciendo la tarde, lo cual está bien.

Otros consejos

Para ayudar a entender por qué utilizar mutable, podemos explorar otras opciones.

Puede resolver el mismo problema utilizando const_cast :

size_t NumberCollection::difficultSize() const
{
     if(!upToDate_)
     {
          NumberCollection& nonConst = const_cast<NumberCollection&>(*this);
          nonConst.difficultSet_ = PerformExpensiveCalculationFunction();
          nonConst.upToDate_ = true;
     }
     // etc....
}

Después de haber ofrecido esta solución, voy a decir que es inferior a la utilización de mutable . Si un miembro se ha marcado como mutable , a continuación, simplemente mirando a la cabecera que he entendido cómo se esté tratando. No entiendo esta información si utiliza const_cast .

Pero entonces alguien podría tomar el otro lado del debate, y decir que es mejor no exponer los detalles de implementación en la cabecera.

Esta es esencialmente la razón C ++ tiene el constructo mutable. de diatriba sobre el mal uso de mutable Alan De Smet muestra los tipos de situaciones en las cuales mutable no debe ser utilizado.

En este caso, difficultSize () no cambia lo que el NumberCollection representa - que es adecuado para el marcado como const. Cómo lo hace alguna vez tiene que cambiar las partes internas, a veces, por lo que usted necesita para marcar difficultSet_ y upToDate_ como mutable.

Su solución está muy bien en C ++ 98. Tenga en cuenta que en C ++ 11 debe tener en cuenta para sincronizar el acceso a sus datos mutables. De lo contrario, es posible que encuentre problemas cuando tu clase es utilizada por el STL, lo que supone que todos los métodos constantes son seguros para subprocesos.

Para más detalles, ver ¿Significa flujos seguros const en C ++ 11?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top