Réponses:
N'importe où dans une unité de compilation (généralement un fichier .cpp) ferait:
foo.h
class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.
static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};
toto.cpp
#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;
(*) Selon les normes, vous devez définir en i
dehors de la définition de classe (comme l' j
est) si elle est utilisée dans du code autre que de simples expressions constantes intégrales. Voir le commentaire de David ci-dessous pour plus de détails.
i
faudrait le définir que s'il était utilisé ailleurs que dans des expressions constantes intégrales, n'est-ce pas? Dans ce cas, vous ne pouvez pas dire qu'il y a une erreur parce qu'il n'y a pas assez de contexte pour être sûr - ou strictement, l'exemple ci-dessus est correct s'il n'y a pas d'autre code. Maintenant, j'apprécie votre commentaire (+1), j'apprends encore des choses moi-même! Je vais donc essayer de clarifier ce point dans la réponse, s'il vous plaît laissez-moi savoir si c'est mieux ...
int f() { return 42; } class foo { static const int i = f(); /* Error! */ }
Notez que C ++ 11 permet d'appeler des fonctions 'constexpr':constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
Les membres statiques doivent être initialisés dans une unité de traduction .cpp à la portée du fichier ou dans l'espace de noms approprié:
const string foo::s( "my foo");
Dans une unité de traduction au sein du même espace de noms, généralement en haut:
// foo.h
struct foo
{
static const std::string s;
};
// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives
// bar.h
namespace baz
{
struct bar
{
static const float f;
};
}
// bar.cpp
namespace baz
{
const float bar::f = 3.1415926535;
}
Depuis C ++ 17, le spécificateur en ligne s'applique également aux variables. Vous pouvez maintenant définir des variables de membre statiques dans la définition de classe:
#include <string>
class foo {
public:
foo();
foo( int );
private:
inline static const std::string s { "foo" };
};
Seules les valeurs intégrales (par exemple static const int ARRAYSIZE
) sont initialisées dans le fichier d'en-tête car elles sont généralement utilisées dans l'en-tête de classe pour définir quelque chose comme la taille d'un tableau. Les valeurs non intégrales sont initialisées dans le fichier d'implémentation.
i
doit être défini dans le cpp. §9.4.2 / 4 Si une donnée membre statique est de type const intégrale ou énumération const, sa déclaration dans la définition de classe peut spécifier un initialiseur de constante qui doit être une expression constante intégrale (5.19). Dans ce cas, le membre peut apparaître dans des expressions constantes intégrales. Le membre doit toujours être défini dans une portée d'espace de nom s'il est utilisé dans le programme et la définition de portée d'espace de nom ne doit pas contenir d'initialiseur.