c++ class static member
Uso de la variable del miembro de C++ Static Const (3)
Dada su descripción de la situación, diría que usar miembros static const
es un buen enfoque. En C ++ 11 es posible que desee convertirlo en static constexpr
para enfatizar que es una constante de compilación, aunque nada cambiará efectivamente como resultado de eso.
Si se refiere a myclass::kMyClassContant_
en algún lugar del código de una manera que sea relevante bajo la regla de una definición (odr), esp. en contextos que requieren una referencia (incluyendo const-reference), el compilador se quejará de que no hay una definición de la constante. Simplemente declararlo e inicializarlo dentro de la clase no es suficiente en este caso. Esto puede obligarte a separar declaración y definición:
// mycode.h
class myclass {
private:
static const uint16_t kMyClassConstant_;
};
// mycode.cpp
const uint16_t myclass::kMyClassConstant_ = 0xBEEF;
Para evitar el problema de mantener declaraciones y definiciones separadas, algunas personas prefieren declarar una función constexpr en línea en lugar de una variable real:
// mycode.h
class myclass {
private:
static constexpr uint16_t kMyClassConstant_()
{ return 0xBEEF; }
};
Esta es una solución alternativa correcta para muchos de los problemas relacionados con la ODR, y no causa ninguna pérdida en el rendimiento. El hecho de que sea realmente útil depende de cuánta carga conlleva mantener declaraciones y definiciones separadas de una constante estática ordinaria. Si espera que sus constantes nunca cambien a medida que evolucione su código, es preferible usar constantes estáticas ordinarias con definiciones separadas. Pero si modifica las definiciones de las constantes con frecuencia, tener que volver a compilar el archivo de definición y volver a vincularlo a todas las partes relevantes del proyecto puede hacer que considere la solución basada en la función anterior como una mejor alternativa.
Un comentario final sobre el tipo de datos: forzarlo a 16 bits usando std::uint16_t
puede ser útil si necesita almacenar muchos de estos valores en forma compacta. De lo contrario, es posible que el tamaño real no sea realmente importante, en cuyo caso std::uint_fast16_t
(que puede tener más de 16 bits) puede ser mejor.
Digamos que tengo una clase que requiere algunas constantes para funcionar. Varias funciones miembro requieren el uso de estas constantes. El uso de #define está mal visto, ya que puede causar colisiones. Las constantes son patrones hexadecimales de 8 o 16 bits y se almacenan como uint8_t o uint16_t. Estas constantes tampoco cambian de una instancia a otra de la clase y, por lo tanto, la memoria (aunque muy poca memoria) se puede guardar al tener solo una copia de las constantes.
¿Hay algo inapropiado, o tal vez una mejor manera de lograr lo anterior en lugar de simplemente hacer algo como lo siguiente:
// mycode.h
// .......
class myclass {
private:
static const uint16_t kMyClassConstant_ = 0xBEEF;
// .......
};
Gracias de antemano por la ayuda.
Desde C ++ 17, tenemos acceso a las variables en inline
, que se ocupan de los problemas relacionados con ODR. Varias opciones:
// mycode.h
class myclass {
static const inline uint16_t kMyClassConstant_ = 0xBEEF;
};
O, si se puede marcar constexpr
(como en este caso):
// mycode.h
class myclass {
static constexpr inline uint16_t kMyClassConstant_ = 0xBEEF;
};
Que se puede simplificar para:
// mycode.h
class myclass {
static constexpr uint16_t kMyClassConstant_ = 0xBEEF;
};
Porque en C ++ 17, constexpr
implica en inline
para miembros de datos static
.
Podrías usar rasgos de tipo para implementar esto:
#include <type_traits>
class myclass {
private:
typedef std::integral_constant<uint16_t , 0xBEEF> kMyClassConstant;
// ...
};
utilizado como myclass::kMyClassConstant::value
.
Esto muestra el propósito de implementar una constante integral y le impide tomar accidentalmente una dirección de la constante.