Avant C++11, nous ne pouvions effectuer une initialisation en classe que sur les membres statiques const de type intégral ou énumération. Stroustrup en parle dans sa FAQ C++. en donnant l'exemple suivant :
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
Et le raisonnement suivant :
Alors pourquoi ces restrictions gênantes existent-elles ? 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 des règles de liaison compliquées, le C++ exige que chaque objet ait une définition unique. Cette règle serait brisée si le C++ autorisait la définition en classe d'entités devant être stockées en mémoire en tant qu'objets.
Toutefois, C++11 assouplit ces restrictions, en autorisant l'initialisation en classe des membres non statiques (§12.6.2/8) :
Dans un constructeur non-délégataire, si un membre de données non statique donné ou une classe de base n'est pas désigné par une balise mem-initializer-id (y compris le cas où il n'y a pas de mem-initializer-list car le constructeur n'a pas de ctor-initialisateur ) et l'entité n'est pas une classe de base virtuelle d'une classe abstraite (10.4), alors
- si l'entité est un membre de données non-statique qui a un initialisateur d'accolade ou d'égalité l'entité est initialisée comme indiqué au point 8.5 ;
- sinon, si l'entité est un membre variant (9.5), aucune initialisation n'est effectuée ;
- sinon, l'entité est initialisée par défaut (8.5).
La section 9.4.2 permet également l'initialisation en classe des membres statiques non-const s'ils sont marqués par l'attribut constexpr
spécificateur.
Alors, qu'est-il advenu des raisons des restrictions que nous avions en C++03 ? Devons-nous simplement accepter les "règles compliquées de l'éditeur de liens" ou quelque chose d'autre a-t-il changé qui rende cela plus facile à mettre en œuvre ?