Pourquoi je ne peux pas initialiser static
données membres de la classe?
La norme C++ permet seulement statique constante intégrale ou énumération des types d'être initialisé à l'intérieur de la classe. C'est la raison pour a
est autorisé à être initialisé alors que d'autres ne le sont pas.
Référence:
C++03 9.4.2 données membres Statiques
§4
Si une donnée membre statique est de const intégrale ou const type d'énumération, sa déclaration dans la définition de classe peut spécifier une constante de l'initialiseur qui doit être une expression constante (5.19). Dans ce cas, le membre peut apparaître dans intégrale des expressions constantes. Le membre doit encore être défini dans un espace de noms portée si elle est utilisée dans le programme et l'espace de noms définition de la portée ne doit pas contenir un initialiseur.
Quels sont les types intégraux?
C++03 3.9.1 types Fondamentaux
§7
Types bool, char, wchar_t, et les entiers signés et non signés types d'entiers sont collectivement appelés les types intégraux.43) Un synonyme de type intégral est de type entier.
Note de bas de page:
43) par conséquent, les énumérations (7.2) ne font pas partie intégrante; toutefois, les énumérations peuvent être promus en int, unsigned int, long, ou unsigned long, comme spécifié au paragraphe 4.5.
Solution de contournement:
Vous pouvez utiliser l' enum astuce pour initialiser un tableau à l'intérieur de votre définition de classe.
class A
{
static const int a = 3;
enum { arrsize = 2 };
static const int c[arrsize] = { 1, 2 };
};
Pourquoi la Norme ne permet pas cela?
Bjarne explique ce bien ici:
Une classe est généralement déclarée dans un fichier d'en-tête et un fichier d'en-tête est généralement inclus dans de nombreuses unités de traduction. Cependant, pour éviter compliqué linker règles, C++ exige que chaque objet a une définition unique. Cette règle serait brisé si C++ admis dans la définition de la classe d'entités qui doivent être stockées dans la mémoire comme des objets.
Pourquoi sont-ils uniquement static const
intégrale des types et des enums admis Dans la classe d'Initialisation?
La réponse est cachée dans Bjarne citation de lire de près,
"C++ exige que chaque objet a une définition unique. Cette règle serait brisé si C++ admis dans la définition de la classe d'entités qui doivent être stockées dans la mémoire comme des objets."
Notez que seuls static const
les nombres entiers peuvent être traités comme de la compilation des constantes de temps. Le compilateur sait que la valeur de l'entier ne va pas changer à tout moment et par conséquent, il peut appliquer sa propre magie et d'appliquer les optimisations du compilateur simplement inlines ces membres de la classe j'.e, ils ne sont pas stockées dans la mémoire de plus, Comme le besoin d'être stockées dans la mémoire est retirée, il donne à ces variables, à l'exception de la règle mentionnée par Bjarne.
Il est intéressant de noter ici que même si static const
des valeurs intégrales peuvent avoir Dans la Classe d'Initialisation, en prenant l'adresse de ces variables n'est pas autorisé. On peut prendre l'adresse d'un membre statique si (et seulement si) il a une définition de classe.Cela valide le raisonnement ci-dessus.
les énumérations sont permis ce parce que les valeurs d'un type énuméré peut être utilisé là où ints sont attendus.voir la citation ci-dessus
Comment ce changement, en C++11?
C++11 détend la restriction, dans une certaine mesure.
C++11 9.4.2 données membres Statiques
§3
Si une donnée membre statique est de const type de littéral, sa déclaration dans la définition de classe peut spécifier un corset ou égal initialiseur dans lequel chaque initialiseur de la clause qui est une affectation-expression est une expression constante. Une donnée membre statique de type de littéral peut être déclaré dans la définition de la classe avec l' constexpr specifier;
si oui, sa déclaration doit indiquer un corset ou égal initialiseur dans lequel chaque initialiseur de la clause qui est une affectation-expression est une expression constante. [ Note: Dans ces deux cas, le membre peut apparaître dans des expressions constantes. -fin de la remarque ] Le membre doit encore être défini dans un espace de noms portée si elle est utilisée dans le programme et l'espace de noms définition de la portée ne doit pas contenir un initialiseur.
Aussi, C++11 va permettre(§12.6.2.8) un non-membre de données statiques être initialisé où elle est déclarée(dans sa catégorie). Cela signifie beaucoup plus facile de l'utilisateur de la sémantique.
Notez que ces fonctions n'ont pas encore été mis en œuvre dans la dernière version de gcc 4.7, de Sorte que vous pourriez encore avoir des erreurs de compilation.