Initialiser les variables statiques dans la Classe C++?
J'ai remarqué que certaines de mes fonctions dans une classe n'accèdent pas à l'objet, donc je les ai faites static
. Ensuite, le compilateur m'a dit que toutes les variables auxquelles ils ont accès doivent également être statiques-Eh bien, tout à fait compréhensible jusqu'à présent. J'ai un tas de variables de chaîne telles que
string RE_ANY = "([^\n]*)";
string RE_ANY_RELUCTANT = "([^\n]*?)";
Et ainsi de suite dans la classe. Je les ai ensuite tous static const
parce qu'ils ne changent jamais. Cependant, mon programme ne compile que si je les déplace hors de la classe: sinon, MSVC++2010 se plaint "seulement statique les variables intégrales constantes peuvent être initialisées dans une classe".
Eh Bien, c'est malheureux. Est-il une solution? Je voudrais les laisser dans la classe à laquelle ils appartiennent.
9 réponses
Ils ne peuvent pas être initialisés dans la classe, mais ils peuvent être initialisés en dehors de la classe, dans un fichier source:
// inside the class
class Thing {
static string RE_ANY;
static string RE_ANY_RELUCTANT;
};
// in the source file
string Thing::RE_ANY = "([^\\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)";
Mise à Jour
Je viens de remarquer la première ligne de votre question - vous ne voulez pas faire ces fonctions static
, vous voulez les faire const
. Les rendre static
signifie qu'ils ne sont plus associés à un objet (donc ils ne peuvent accéder à aucun membre non statique), et rendre les données statiques signifie qu'elles seront partagées avec tous les objets de ceci type. Cela pourrait bien ne pas être ce que vous voulez. Les faire const
signifie simplement qu'ils ne peuvent modifier aucun membre, mais peuvent toujours y accéder.
Mike Seymour vous a donné la bonne réponse, mais pour ajouter...
C++ vous permet de déclarer et de définir dans votre corps de classe uniquement static const integral types , comme le dit le compilateur. Donc, vous pouvez réellement faire:
class Foo
{
static const int someInt = 1;
static const short someShort = 2;
// etc.
};
Et vous ne pouvez pas le faire avec un autre type, dans ce cas, vous devez les définir dans votre .fichier cpp.
Les variables membres statiques doivent être déclarées dans la classe, puis définies en dehors de celle-ci!
Il n'y a pas de solution de contournement, il suffit de mettre leur définition réelle dans un fichier source.
D'après votre description, il semble que vous n'utilisiez pas les variables statiques de la bonne façon. Si elles ne changent jamais, vous devriez utiliser une variable constante à la place, mais votre description est trop générique pour en dire plus.
Les variables membres statiques ont toujours la même valeur pour n'importe quelle instance de votre classe: si vous modifiez une variable statique d'un objet, elle changera également pour tous les autres objets (et en fait vous pouvez également y accéder sans une instance de la classe - ie: un objet).
Depuis C++11, cela peut être fait dans une classe avec constexpr
.
class stat {
public:
// init inside class
static constexpr double inlineStaticVar = 22;
};
La variable est maintenant accessible avec:
stat::inlineStaticVar
Je pense qu'il vaut la peine d'ajouter qu'une variable statique n'est pas la même chose qu'une variable constante.
Utilisation d'une variable constante dans une classe
struct Foo{
const int a;
Foo(int b) : a(b){}
}
Et nous le déclarerions comme tel
fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;
Pour une variable statique
struct Bar{
static int a;
Foo(int b){
a = b;
}
}
Bar::a = 0; // set value for a
Qui est utilisé comme ceci
barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;
Vous voyez ce qui se passe ici. La variable constante, qui est instanciée avec chaque instance de Foo, comme Foo est instanciée a une valeur distincte pour chaque instance de Foo, et elle ne peut pas être modifiée par Foo à tous.
Où comme avec Bar, leur est seulement une valeur pour Bar:: a peu importe combien d'instances de Bar sont faites. Ils partagent tous cette valeur, vous pouvez également y accéder avec leurs instances de Bar. La variable statique respecte également les règles pour public / private, vous pouvez donc faire en sorte que seules les instances de Bar puissent lire la valeur de Bar:: a;
Juste pour ajouter au-dessus des autres réponses. Pour initialiser un complexe membre statique, vous pouvez le faire comme suit:
Déclarez votre membre statique comme d'habitude.
// myClass.h
class myClass
{
static complexClass s_complex;
//...
};
Créez une petite fonction pour initialiser votre classe si ce n'est pas trivial de le faire. Cela sera appelé juste la seule fois que le membre statique est initialisé. (Notez que le constructeur de copie de complexClass sera utilisé, il devrait donc être bien défini).
//class.cpp
#include myClass.h
complexClass initFunction()
{
complexClass c;
c.add(...);
c.compute(...);
c.sort(...);
// Etc.
return c;
}
complexClass myClass::s_complex = initFunction();
Si votre but est d'initialiser la variable statique dans votre fichier d'en-tête (au lieu d'un *.fichier cpp, que vous voudrez peut-être si vous vous en tenez à un idiome "en-tête seulement"), vous pouvez contourner le problème d'initialisation en utilisant un modèle. Les variables statiques modélisées peuvent être initialisées dans un en-tête, sans que plusieurs symboles soient définis.
Voir ici pour un exemple:
Optionnellement, Déplacez toutes vos constantes vers .fichier cpp sans déclaration .h fichier. Utilisez l'espace de noms anonyme pour les rendre invisibles au-delà du module cpp.
// MyClass.cpp
#include "MyClass.h"
// anonymous namespace
namespace
{
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
}
// member function (static or not)
bool MyClass::foo()
{
// logic that uses constants
return RE_ANY_RELUCTANT.size() > 0;
}
Certaines réponses semblent être trompeuse un peu.
Vous n'avez pas à
- Affecter une valeur à l'objet statique lors de l'initialisation, l'attribution d'une valeur est Optionnel.
- créez un autre fichier
.cpp
pour l'initialiser, il peut être fait de même dans le fichier Header.
#ifndef CLASS_A_H
#define CLASS_A_H
#include <string>
class A
{
private:
static std::string str;
static int x;
};
// Initialize with no values
std::string A::str;
int A::x;
// Initialize with values
//std::string A::str = "SO!";
//int A::x = 900;
#endif