¿Cómo inicializar la variable miembro const en una clase?

105
#include <iostream>

using namespace std;
class T1
{
  const int t = 100;
  public:

  T1()
  {

    cout << "T1 constructor: " << t << endl;
  }
};

Cuando intento inicializar la variable miembro const tcon 100. Pero me da el siguiente error:

test.cpp:21: error: ISO C++ forbids initialization of member t
test.cpp:21: error: making t static

¿Cómo puedo inicializar un constvalor?

Chaitanya
fuente
8
con c ++ 11, esto es posible, verifique este enlace stackoverflow.com/questions/13662441/…
Kapil

Respuestas:

122

La constvariable especifica si una variable es modificable o no. El valor constante asignado se utilizará cada vez que se haga referencia a la variable. El valor asignado no se puede modificar durante la ejecución del programa.

La explicación de Bjarne Stroustrup lo resume brevemente:

Por lo general, una clase se declara en un archivo de encabezado y un archivo de encabezado generalmente se incluye en muchas unidades de traducción. Sin embargo, para evitar reglas complicadas del enlazador, C ++ requiere que cada objeto tenga una definición única. Esa regla se rompería si C ++ permitiera la definición en clase de entidades que deben almacenarse en la memoria como objetos.

Una constvariable debe declararse dentro de la clase, pero no puede definirse en ella. Necesitamos definir la variable const fuera de la clase.

T1() : t( 100 ){}

Aquí la asignación t = 100ocurre en la lista de inicializadores, mucho antes de que ocurra la inicialización de la clase.

Dinkar Thakur
fuente
3
¿Puede ser un poco más detallado sobre la última declaración que Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.no entendí? Y básicamente ese tipo de definición de permisos dentro de la clase es específico del compilador, ¿verdad?
Chaitanya
3
¿Qué asignación i = 10?
Daniel Daranas
Tengo constantes en mi clase que inicializo de la forma anterior. Sin embargo, cuando intento crear un objeto de esa clase, me da un error al decir eso operator = function not founden VC ++. ¿Cual puede ser el problema?
Rohit Shinde
4
Cuando usa las palabras exactas de alguien sin atribución, se llama plagio. Utilice la atribución adecuada: consulte stroustrup.com/bs_faq2.html#in-class y stackoverflow.com/questions/13662441/…
Tanaya
Sí, tampoco entiendo totalmente el código en la respuesta, ¿qué diablos es eso? ¿Se puede colocar en la implementación del archivo cpp?
Tomáš Zato - Reincorporación a Monica
50

Bueno, podrías hacerlo static:

static const int t = 100;

o puede usar un inicializador de miembros:

T1() : t(100)
{
    // Other constructor stuff here
}
Fred Larson
fuente
2
Para su uso (y / o intenciones), sería mucho mejor hacerlo estático.
Mark García
@FredLarson ¿Es como si algunas versiones de g ++ no permitan ese tipo de inicializaciones? o ¿No está permitido en absoluto?
Chaitanya
3
@Chaitanya: C ++ 11 Los inicializadores de miembros no estáticos se implementan desde gcc 4.7.
Jesse Good
@MarkGarcia ¿por qué mucho mejor? podría ser un requisito si const memberdebería ser accesible desde las funciones / objetos, entonces ¿por qué estático?
Asif Mushtaq
Aunque por lo general es engañoso dar un ejemplo a los principiantes de estática. Porque es posible que no sepan que es solo una para todas las instancias (objetos) de esa clase.
Muhamed Cicak
30

Hay un par de formas de inicializar los miembros const dentro de la clase.

Definición de miembro const en general, también necesita inicialización de la variable.

1) Dentro de la clase, si desea inicializar la constante, la sintaxis es así

static const int a = 10; //at declaration

2) La segunda forma puede ser

class A
{
  static const int a; //declaration
};

const int A::a = 10; //defining the static member outside the class

3) Bueno, si no desea inicializar en la declaración, la otra forma es a través del constructor, la variable debe inicializarse en la lista de inicialización (no en el cuerpo del constructor). Tiene que ser asi

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};
ravs2627
fuente
8
Creo que esta respuesta necesita una aclaración. El uso de la palabra clave estática para un miembro de la clase no es agregar una sintaxis arbitraria para hacer feliz al compilador. Significa que hay una única copia de la variable para todas las instancias del objeto, constante o no. Es una elección de diseño que debe considerarse detenidamente. En el futuro, el programador podría decidir que este miembro de clase constante aún podría variar con diferentes objetos, a pesar de permanecer constante durante la vida útil de un objeto dado.
opetrenko
De acuerdo ... Cuando usamos estática, crea solo una copia para todos los objetos ... Como mencionaste, es una elección de diseño. En caso de una sola copia para todos los objetos 1 y 2 debería funcionar. En el caso de una copia individual para cada objeto, 3 funcionarían
ravs2627
Esta respuesta sugiere un cambio de sintaxis simple sin consecuencias, mientras que cambiarlo para que sea estático no lo es.
Isaac Woods
¿Qué sucede si necesita usar double o float? ¿Es esto parte del estándar C ++ 11?
serup
14

Si no desea que el constmiembro de datos de la clase sea estático, puede inicializar el constmiembro de datos utilizando el constructor de la clase. Por ejemplo:

class Example{
      const int x;
    public:
      Example(int n);
};

Example::Example(int n):x(n){
}

si hay varios constmiembros de datos en la clase, puede usar la siguiente sintaxis para inicializar los miembros:

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}
GANESH BK
fuente
3
Creo que esto proporciona una mejor respuesta que la que se aceptó ....
Ian
1
¡Gracias por los ejemplos claros como el cristal y la variante que muestra una pluralidad! ¡Se eliminó la ambigüedad y la investigación / desplazamiento adicional por parte del lector!
luz clara
13
  1. Puede actualizar su compilador para que sea compatible con C ++ 11 y su código funcionará perfectamente.

  2. Use la lista de inicialización en el constructor.

    T1() : t( 100 )
    {
    }
borisbn
fuente
6

Otra solucion es

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

Entonces t se inicializa en 100 y no se puede cambiar y es privado.

Almizclado
fuente
3

Si un miembro es una matriz, será un poco más complejo de lo normal:

class C
{
    static const int ARRAY[10];
 public:
    C() {}
};
const unsigned int C::ARRAY[10] = {0,1,2,3,4,5,6,7,8,9};

o

int* a = new int[N];
// fill a

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};
Viet Anh Do
fuente
2

Otra forma posible son los espacios de nombres:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

class T1
{
   public:
   T1()
   {
       cout << "T1 constructor: " << mySpace::T << endl;
   }
};

La desventaja es que otras clases también pueden usar las constantes si incluyen el archivo de encabezado.

Baran
fuente
1

Esta es la forma correcta de hacerlo. Puedes probar este código.

#include <iostream>

using namespace std;

class T1 {
    const int t;

    public:
        T1():t(100) {
            cout << "T1 constructor: " << t << endl;
        }
};

int main() {
    T1 obj;
    return 0;
}

si está utilizando C++10 Compiler or below, no puede inicializar el miembro de contras en el momento de la declaración. Entonces, aquí es necesario hacer que el constructor inicialice el miembro de datos const. También es necesario utilizar la lista de inicializadores T1():t(100)para obtener memoria al instante.

Jugador Aziz
fuente
0

puede agregar staticpara hacer posible la inicialización de esta variable miembro de clase.

static const int i = 100;

Sin embargo, esta no siempre es una buena práctica para usar dentro de la declaración de clase, porque todos los objetos instalados de esa clase compartirán la misma variable estática que se almacena en la memoria interna fuera de la memoria de alcance de los objetos instanciados.

dhokar.w
fuente