Como inicializar a variável de membro const em uma classe?

105
#include <iostream>

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

  T1()
  {

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

Quando estou tentando inicializar a variável const membro tcom 100. Mas está me dando o seguinte erro:

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

Como posso inicializar um const valor?

Chaitanya
fonte
8
com c ++ 11, isso é possível, verifique este link stackoverflow.com/questions/13662441/…
Kapil

Respostas:

122

o const variável especifica se uma variável é modificável ou não. O valor constante atribuído será usado cada vez que a variável for referenciada. O valor atribuído não pode ser modificado durante a execução do programa.

A explicação de Bjarne Stroustrup resume tudo brevemente:

Uma classe é normalmente declarada em um arquivo de cabeçalho e um arquivo de cabeçalho é normalmente incluído em muitas unidades de tradução. No entanto, para evitar regras complicadas do vinculador, C ++ exige que cada objeto tenha uma definição exclusiva. Essa regra seria quebrada se C ++ permitisse a definição na classe de entidades que precisavam ser armazenadas na memória como objetos.

Uma constvariável deve ser declarada dentro da classe, mas não pode ser definida nela. Precisamos definir a variável const fora da classe.

T1() : t( 100 ){}

Aqui, a atribuição t = 100acontece na lista de inicializadores, muito antes de ocorrer a inicialização da classe.

Dinkar Thakur
fonte
3
Você pode ser um pouco mais elaborado sobre a última afirmação Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.que não entendi. E basicamente esse tipo de permissão de definições dentro da classe é específico do compilador, certo?
Chaitanya
3
O que i = 10 atribuição?
Daniel Daranas
Tenho constantes em minha classe que inicializo da maneira acima. No entanto, quando tento criar um objeto dessa classe, ocorre um erro dizendo isso operator = function not foundem VC ++. Qual pode ser o problema?
Rohit Shinde
4
Quando você usa as palavras exatas de alguém sem atribuição, isso é chamado de plágio. Use a atribuição adequada - consulte stroustrup.com/bs_faq2.html#in-class e stackoverflow.com/questions/13662441/…
Tanaya
Sim, eu também não entendo totalmente o código da resposta - o que diabos é isso? Ele pode ser colocado na implementação do arquivo cpp?
Tomáš Zato - Reintegrar Monica em
50

Bem, você poderia fazer isso static:

static const int t = 100;

ou você pode usar um inicializador de membro:

T1() : t(100)
{
    // Other constructor stuff here
}
Fred Larson
fonte
2
Para seu uso (e / ou intenções), seria muito melhor torná-lo estático.
Mark Garcia
@FredLarson É como se algumas versões do g ++ não permitissem esse tipo de inicialização? ou não é permitido de todo?
Chaitanya
3
@Chaitanya: C ++ 11 Os inicializadores de membros não estáticos são implementados a partir do gcc 4.7.
Jesse Good
@MarkGarcia porque muito melhor? poderia ser um requisito se const memberdeveria ser acessível a partir das funções / objetos, então por que estático?
Asif Mushtaq de
Embora geralmente seja enganoso dar um exemplo para iniciantes de estática. Porque, eles podem não saber que é apenas um para todas as instâncias (objetos) dessa classe.
Muhamed Cicak
30

Existem algumas maneiras de inicializar os membros const dentro da classe.

Definição de membro const em geral, também precisa da inicialização da variável.

1) Dentro da classe, se você deseja inicializar o const a sintaxe é assim

static const int a = 10; //at declaration

2) A segunda via pode ser

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

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

3) Bem, se você não quiser inicializar na declaração, a outra maneira é por meio do construtor, a variável precisa ser inicializada na lista de inicialização (não no corpo do construtor). Tem que ser assim

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};
ravs2627
fonte
8
Acho que essa resposta precisa de esclarecimento. O uso da palavra-chave estática para um membro da classe não adiciona nenhuma sintaxe arbitrária para deixar o compilador feliz. Significa que existe uma única cópia da variável para todas as instâncias do objeto, constantes ou não. É uma escolha de design que deve ser considerada com cuidado. No futuro, o programador pode decidir que esse membro da classe constante ainda pode variar com diferentes objetos, apesar de permanecer constante durante a vida útil de um determinado objeto.
opetrenko
Concordo .. Quando usamos estático, ele cria apenas uma cópia dele para todos os objetos .. Como você mencionou, é uma escolha de design. No caso de cópia única para todos os objetos 1 e 2 deve funcionar. No caso de cópia individual para cada objeto, 3 funcionaria
ravs2627
Essa resposta sugere uma mudança de sintaxe simples sem consequências - ao passo que mudá-la para estática não é.
Isaac Woods
e se você precisar usar double ou float - isso faz parte do padrão C ++ 11?
serup
14

Se você não deseja tornar o constmembro de dados estático na classe, pode inicializar o constmembro de dados usando o construtor da classe. Por exemplo:

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

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

se houver vários constmembros de dados na classe, você pode usar a seguinte sintaxe para inicializar os membros:

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}
GANESH BK
fonte
3
Acho que isso fornece uma resposta melhor do que a que foi aceita ...
Ian
1
Obrigado pelos exemplos claros e pela variante mostrando uma pluralidade! Ambigüidade eliminada e pesquisa extra / rolagem por parte do leitor!
clearlight
13
  1. Você pode atualizar seu compilador para suportar C ++ 11 e seu código funcionaria perfeitamente.

  2. Use a lista de inicialização no construtor.

    T1() : t( 100 )
    {
    }
Borisbn
fonte
6

Outra solução é

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

Portanto, t é inicializado com 100 e não pode ser alterado e é privado.

Almiscarado
fonte
3

Se um membro for um Array, será um pouco mais complexo do que o 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};

ou

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

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

Outra forma possível são os namespaces:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

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

A desvantagem é que outras classes também podem usar as constantes se incluírem o arquivo de cabeçalho.

Baran
fonte
1

Esta é a maneira certa de fazer. Você pode tentar 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;
}

se estiver usando C++10 Compiler or below, não será possível inicializar o membro contras no momento da declaração. Portanto, aqui é necessário fazer o construtor para inicializar o membro de dados const. Também é necessário usar a lista de inicializadores T1():t(100)para obter memória instantaneamente.

Gambler Aziz
fonte
0

você pode adicionar staticpara tornar possível a inicialização desta variável de membro de classe.

static const int i = 100;

No entanto, nem sempre é uma boa prática usar a declaração de classe interna, porque todos os objetos instanciados dessa classe compartilharão a mesma variável estática que é armazenada na memória interna fora da memória de escopo dos objetos instanciados.

dhokar.w
fonte