29 votes

Comment initialiser un membre statique constant en C++ ?

Est-il possible d'initialiser une valeur statique constante en dehors du constructeur ? Peut-on l'initialiser au même endroit où se trouvent les déclarations de membres ?

class A {
private:
  static const int a = 4;
  /*...*/
};

37voto

Membres de données statiques (C++ uniquement)

La déclaration d'un membre statique dans la liste des membres d'une classe n'est pas une définition. Vous devez définir le membre statique en dehors de la déclaration de la classe, dans l'espace de nom. Par exemple :

class X
{
public:
      static int i;
};
int X::i = 0; // definition outside class declaration

Une fois que vous avez défini un membre de données statique, il existe même si aucun objet de la classe du membre de données statique n'existe. Dans l'exemple ci-dessus, aucun objet de la classe X n'existe, même si le membre statique X::i a été défini.

Les membres de données statiques d'une classe dans l'espace de nom ont un lien externe. L'initialisateur d'un membre de données statiques se trouve dans la portée de la classe qui déclare le membre.

Un membre de données statique peut être de n'importe quel type, sauf void ou void qualifié de const ou volatile. Vous ne pouvez pas déclarer un membre de données statique comme étant mutable.

Vous ne pouvez avoir qu'une seule définition d'un membre statique dans un programme. Les classes non nommées, les classes contenues dans des classes non nommées et les classes locales ne peuvent pas avoir de membres statiques.

Les membres statiques des données et leurs initialisateurs peuvent accéder aux autres membres statiques privés et protégés de leur classe. L'exemple suivant montre comment vous pouvez initialiser des membres statiques en utilisant d'autres membres statiques, même si ces membres sont privés :

class C {
      static int i;
      static int j;
      static int k;
      static int l;
      static int m;
      static int n;
      static int p;
      static int q;
      static int r;
      static int s;
      static int f() { return 0; }
      int a;
public:
      C() { a = 0; }
      };

C c;
int C::i = C::f();    // initialize with static member function
int C::j = C::i;      // initialize with another static data member
int C::k = c.f();     // initialize with member function from an object
int C::l = c.j;       // initialize with data member from an object
int C::s = c.a;       // initialize with nonstatic data member
int C::r = 1;         // initialize with a constant value

class Y : private C {} y;

int C::m = Y::f();
int C::n = Y::r;
int C::p = y.r;       // error
int C::q = y.f();     // error

Les initialisations de C::p et C::q provoquent des erreurs car y est un objet d'une classe dérivée privée de C, et ses membres ne sont pas accessibles aux membres de C.

Si un membre de données statique est de type const integral ou const enumeration, vous pouvez spécifier un initialisateur constant dans la déclaration du membre de données statique. Cet initialisateur constant doit être une expression constante intégrale. Notez que l'initialisateur de constante n'est pas une définition. Vous devez toujours définir le membre statique dans un espace de nom englobant. L'exemple suivant en fait la démonstration :

#include <iostream>
using namespace std;

struct X {
  static const int a = 76;
};

const int X::a;

int main() {
  cout << X::a << endl;
}

Le jeton = 76 à la fin de la déclaration du membre de données statique a est un initialisateur de constante.

35voto

Klaim Points 24511

OUI, vous le pouvez, mais seulement pour les types int. Si vous voulez que votre membre statique soit d'un autre type, vous devrez le définir quelque part dans un fichier cpp.

class A{
private:
 static const int a = 4; // valid
 static const std::string t ; // can't be initialized here
 ...
 ...
};

// in a cpp file where the static variable will exist 
const std::string A::t = "this way it works";

Notez également que cette règle a été supprimée dans C++11, maintenant (avec un compilateur fournissant la fonctionnalité) vous pouvez initialiser ce que vous voulez directement dans la déclaration des membres de la classe.

7voto

Chubsdad Points 14310

Par souci d'exhaustivité, j'ajoute les variables membres statiques du modèle.

template<class T> struct X{
   static T x;
};

template<class T> T X<T>::x = T();

int main(){
   X<int> x;
}

3voto

sbi Points 100828

Vous ne pouvez pas initialiser les membres statiques dans les constructeurs. Les types intégraux peuvent être initialisés en ligne lors de leur déclaration. Les autres membres statiques doivent être définis (dans un .cpp ) :

// .h
class A{
private:
 static const int a = 4;
 static const foo bar;
 ...
 ...
};

// .cpp
const foo A::bar = ...;

0voto

Ricko M Points 745

Si je me souviens bien, vous ne pouvez pas le définir à l'intérieur de la classe. Vous devez explicitement le définir à l'extérieur comme mentionné par pablo.

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