Dans PHP et C #, les constantes peuvent être initialisées lorsqu'elles sont déclarées:
class Calendar3
{
const int value1 = 12;
const double value2 = 0.001;
}
J'ai la déclaration C++ suivante d'un foncteur qui est utilisé avec une autre classe pour comparer deux vecteurs mathématiques:
struct equal_vec
{
bool operator() (const Vector3D& a, const Vector3D& b) const
{
Vector3D dist = b - a;
return ( dist.length2() <= tolerance );
}
static const float tolerance = 0.001;
};
Ce code compilé sans problèmes avec g ++. Maintenant en mode C++ 0x (-std = c ++ 0x) le compilateur g ++ génère un message d'erreur:
erreur: "constexpr" nécessaire pour l'initialisation en classe des données statiques "tolérance" de type non intégral
Je sais que je peux définir et initialiser cette static const
membre en dehors de la définition de classe. De plus, un membre de données constant non statique peut être initialisé dans la liste d'initialisation d'un constructeur.
Mais existe-t-il un moyen d'initialiser une constante dans une déclaration de classe, comme cela est possible dans PHP ou C #?
J'ai utilisé le mot clé static
simplement parce qu'il était possible d'initialiser de telles constantes dans la déclaration de classe en g ++. J'ai juste besoin d'un moyen d'initialiser une constante dans une déclaration de classe, peu importe si elle est déclarée comme static
ou non.
En C++ 11, non -static
membres de données, static constexpr
membres de données, et static const
Les données membres de type intégrale ou énumération peuvent être initialisées dans la déclaration de classe. par exemple.
struct X {
int i=5;
const float f=3.12f;
static const int j=42;
static constexpr float g=9.5f;
};
Dans ce cas, le membre i
de toutes les instances de la classe X
est initialisé à 5
par le constructeur généré par le compilateur et le membre f
est initialisé à 3.12
. Le static const
Le membre de données j
est initialisé à 42
, et le static constexpr
Le membre de données g
est initialisé à 9.5
.
Puisque float
et double
ne sont ni de type intégral ni d’énumération, ces membres doivent être soit constexpr
, soit non-static
pour que l’initialiseur de la la définition de classe est autorisée.
Avant C++ 11, uniquement static const
Les membres de données de type intégral ou énumération pourraient avoir des initialiseurs dans la définition de classe.
L'initialisation de variables membres statiques autres que les types const int n'est pas une norme C++ antérieure à C++ 11. Le compilateur gcc ne vous préviendra pas (et produira néanmoins du code utile) à moins que vous ne spécifiiez le -pedantic
option. Vous devriez alors avoir une erreur similaire à:
const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression
const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]
La raison en est que la norme C++ ne spécifie pas comment la virgule flottante doit être implémentée et est laissée au processeur. Pour contourner cela et d'autres limitations, constexpr
a été introduit.
Oui. Ajoutez simplement le mot clé constexpr
comme le dit l'erreur.
Si vous n'en avez besoin que dans l'une des méthodes, vous pouvez le déclarer localement statique:
struct equal_vec
{
bool operator() (const Vector3D& a, const Vector3D& b) const
{
static const float tolerance = 0.001f;
Vector3D dist = b - a;
return ( dist.length2() <= tolerance );
}
};
Cela me posait de réels problèmes, car j’avais besoin du même code pour compiler des versions différentes de g ++ (le compilateur GNU C++). Il me fallait donc utiliser une macro pour voir quelle version du compilateur a été utilisé, puis agissez en conséquence, comme si
#if __GNUC__ > 5
#define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr
#else
#define GNU_CONST_STATIC_FLOAT_DECLARATION const
#endif
GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;
Ceci utilisera 'const' pour tout ce qui était antérieur à g ++ version 6.0.0, puis 'constexpr' pour g ++ version 6.0.0 et ultérieure. C'est un deviner à la version où le changement a lieu, parce que franchement je ne l'avais pas remarqué jusqu'à la version g ++ 6.2.1. Pour le faire correctement, vous devrez peut-être regarder la version mineure et le numéro de correctif de g ++.
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
pour plus de détails sur les macros disponibles.
Avec gnu, vous pouvez aussi vous en tenir à utiliser 'const' partout puis compiler avec le -fpermissive
drapeau, mais cela donne des avertissements et j'aime bien compiler proprement mes affaires.
Pas génial, car il est spécifique aux compilateurs GNU, mais je suppose que vous pourriez faire la même chose avec d’autres compilateurs.