C ++ donde inicializar const estática

129

Tengo una clase

class foo {
public:
   foo();
   foo( int );
private:
   static const string s;
};

¿Dónde está el mejor lugar para inicializar la cadena sen el archivo fuente?

Thomas
fuente

Respuestas:

178

Cualquier lugar en una unidad de compilación (generalmente un archivo .cpp) haría:

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.
};

foo.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;

(*) De acuerdo con los estándares, debe definir ifuera de la definición de clase (como jes) si se usa en un código que no sea solo expresiones constantes integrales. Vea el comentario de David a continuación para más detalles.

chirrido
fuente
27
He votado a favor, pero después de revisar el estándar hay un error en su código: idebe definirse en el cpp. §9.4.2 / 4 Si un miembro de datos estáticos es de tipo const integral o de enumeración const, su declaración en la definición de clase puede especificar un inicializador constante que será una expresión constante integral (5.19). En ese caso, el miembro puede aparecer en expresiones constantes integrales. El miembro aún se definirá en un ámbito de espacio de nombres si se usa en el programa y la definición del ámbito de espacio de nombres no contendrá un inicializador.
David Rodríguez - dribeas
3
Según su cita de los estándares, parece ique tendría que definirse solo si se usara en otro lugar que no sea en expresiones constantes integrales, ¿verdad? En este caso, no puede decir que hay un error porque no hay suficiente contexto para estar seguro, o hablando estrictamente, el ejemplo anterior es correcto si no hay otro código. Ahora aprecio tu comentario (+1), ¡todavía estoy aprendiendo cosas! Así que intentaré aclarar ese punto en la respuesta, por favor avíseme si es mejor ...
squelart
@squelart Lo siento si sueno tonto, pero sería un ejemplo de enunciado distinto de la expresión constante integral.
Saksham
3
@Saksham Por ejemplo, llamar a una función, por ejemplo: tenga en int f() { return 42; } class foo { static const int i = f(); /* Error! */ }cuenta que C ++ 11 permite llamar a las funciones 'constexpr':constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
squelart
@squelart Leí el texto de modo que la definición debe proporcionarse si el miembro se usa en absoluto; la redacción en el estándar no limita ese requisito a expresiones constantes integrales.
VladLosev el
12

Los miembros estáticos deben inicializarse en una unidad de traducción .cpp en el ámbito del archivo o en el espacio de nombres apropiado:

const string foo::s( "my foo");
Michael Burr
fuente
11

En una unidad de traducción dentro del mismo espacio de nombres, generalmente en la parte superior:

// 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;
}
GManNickG
fuente
8

Desde C ++ 17, el especificador en línea también se aplica a las variables. Ahora puede definir variables miembro estáticas en la definición de clase:

#include <string>

class foo {
public:
   foo();
   foo( int );
private:
   inline static const std::string s { "foo" };
};
plexando
fuente
1

Solo los valores integrales (por ejemplo, static const int ARRAYSIZE) se inicializan en el archivo de encabezado porque generalmente se usan en el encabezado de clase para definir algo como el tamaño de una matriz. Los valores no integrales se inicializan en el archivo de implementación.

Behnam Dezfouli
fuente