77 votes

Initialisation d'un membre const dans la déclaration de classe en C ++

En PHP et C# les constantes peuvent être initialisé comme ils sont déclarées:

class Calendar3
{
    const int value1 = 12;
    const double value2 = 0.001;
}

J'ai le C++ suivant la déclaration 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 est compilé sans problèmes avec g++. Maintenant en C++0x mode (-std=c++0x) le compilateur g++ renvoie un message d'erreur:

erreur: ‘constexpr "nécessaire pour l'initialisation de classe de la donnée membre statique de "tolérance" de la non-type intégral

Je sais que je peux définir et initialiser cette static const membre en dehors de la définition de la classe. Aussi, un non-constante statique membre de données peuvent être initialisées dans la liste d'initialiseur d'un constructeur.

Mais est-il possible d'initialiser une constante dans la déclaration de classe, tout comme il est possible en PHP ou C#?

Mise à jour

J'ai utilisé static mot-clé juste parce qu'il a été possible d'initialiser ces constantes dans la déclaration de classe de g++. J'ai juste besoin d'un moyen d'initialiser une constante dans une déclaration de classe, peu importe si elle a déclaré qu' static ou pas.

129voto

Anthony Williams Points 28904

En C++11, non-static de membres de données, static constexpr de données des membres, et static const des membres de données intégrales ou de type énumération peut être initialisé 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, l' i membre de toutes les instances de la classe X est initialisé à l' 5 par l'généré par le compilateur constructeur, et l' f membre est initialisé à l' 3.12. L' static const membre de données j est initialisé à l' 42, et l' static constexpr membre de données g est initialisé à l' 9.5.

Depuis float et double ne sont pas d'intégrales ou de type énumération, ces membres doivent être constexpr, ou de non-static pour l'initialiseur, dans la définition de classe pour être autorisée.

Avant C++11, seulement static const des membres de données intégrales ou de type énumération pourrait avoir des initialiseurs dans la définition de classe.

44voto

Florian Points 743

L'initialisation de membre statique des variables autres que const int types n'est pas standard C++ avant C++11. Le compilateur gcc ne vais pas vous avertir à ce sujet (et de produire de l'utile code néanmoins), sauf si vous spécifiez l' -pedantic option. Ensuite, vous devriez obtenir une erreur semblable à:

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 pour cela est que la norme C++ ne permet pas de spécifier comment virgule flottante doit être mis en œuvre et est laissé pour le processeur. Pour contourner ce problème et d'autres limitations constexpr a été introduit.

11voto

StilesCrisis Points 8388

Oui. Ajoutez simplement le mot clé constexpr comme le dit l'erreur.

1voto

Peter Wood Points 4536

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 );
    }
};
 

0voto

bavaza Points 1747

Eh bien, pas exactement une réponse directe, mais une raison spécifique de ne pas utiliser une macro?

 #define tolerance 0.001
struct equal_vec
{
    bool operator() (const Vector3D& a, const Vector3D& b) const
    { 
        Vector3D dist = b - a;
        return ( dist.length2() <= tolerance );
    }
};
 

Pas vraiment une bonne pratique en C #, mais à mon humble avis, parfaitement légitime en C ++.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X