Comment initialiser la variable membre const dans une classe?

105
#include <iostream>

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

  T1()
  {

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

Lorsque j'essaie d'initialiser la variable membre const tavec 100. Mais cela me donne l'erreur suivante:

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

Comment puis-je initialiser une constvaleur?

Chaitanya
la source
8
avec c ++ 11 c'est possible vérifier ce lien stackoverflow.com/questions/13662441/…
Kapil

Réponses:

123

La constvariable spécifie si une variable est modifiable ou non. La valeur constante attribuée sera utilisée chaque fois que la variable est référencée. La valeur attribuée ne peut pas être modifiée pendant l'exécution du programme.

L' explication de Bjarne Stroustrup le résume brièvement:

Une classe est généralement déclarée dans un fichier d'en-tête et un fichier d'en-tête est généralement inclus dans de nombreuses unités de traduction. Cependant, pour éviter les règles compliquées de l'éditeur de liens, C ++ exige que chaque objet ait une définition unique. Cette règle serait rompue si C ++ autorisait la définition en classe d'entités qui devaient être stockées en mémoire en tant qu'objets.

Une constvariable doit être déclarée dans la classe, mais elle ne peut pas y être définie. Nous devons définir la variable const en dehors de la classe.

T1() : t( 100 ){}

Ici, l'affectation t = 100se produit dans la liste d'initialisation, bien avant l'initialisation de la classe.

Dinkar Thakur
la source
3
Pouvez-vous être un peu plus en détail sur la dernière déclaration que Here the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.je ne comprends pas. Et fondamentalement, ce genre de définition d'autorisation dans la classe est spécifique au compilateur, n'est-ce pas?
Chaitanya
3
Quelle affectation i = 10?
Daniel Daranas
J'ai des constantes dans ma classe que j'initialise de la manière ci-dessus. Cependant, lorsque j'essaie de créer un objet de cette classe, cela me donne une erreur en disant cela operator = function not founddans VC ++. Quel peut être le problème?
Rohit Shinde
4
Lorsque vous utilisez les mots exacts de quelqu'un sans attribution, cela s'appelle du plagiat. Veuillez utiliser une attribution appropriée - voir stroustrup.com/bs_faq2.html#in-class et stackoverflow.com/questions/13662441/…
Tanaya
Ouais, je ne comprends pas du tout le code de la réponse - qu'est-ce que c'est que ça? Peut-il être placé dans l'implémentation de fichier cpp?
Tomáš Zato - Réintégrer Monica
50

Eh bien, vous pourriez le faire static:

static const int t = 100;

ou vous pouvez utiliser un initialiseur de membre:

T1() : t(100)
{
    // Other constructor stuff here
}
Fred Larson
la source
2
Pour son usage (et / ou ses intentions), il serait bien préférable de le rendre statique.
Mark Garcia
@FredLarson Est-ce que certaines versions de g ++ ne permettent pas ce genre d'initialisations? ou Ce n'est pas du tout autorisé?
Chaitanya
3
@Chaitanya: C ++ 11 Les initialiseurs de membres non statiques sont implémentés à partir de gcc 4.7.
Jesse Good
@MarkGarcia pourquoi beaucoup mieux? il pourrait être sur demande si const memberdevrait être accessible à partir des fonctions / objets alors pourquoi statique?
Asif Mushtaq
Bien qu'il soit généralement trompeur de donner un exemple aux débutants en statique. Parce qu'ils ne savent peut-être pas que c'est une seule pour toutes les instances (objets) de cette classe.
Muhamed Cicak
30

Il existe plusieurs façons d'initialiser les membres const à l'intérieur de la classe.

Définition du membre const en général, nécessite également l'initialisation de la variable.

1) À l'intérieur de la classe, si vous voulez initialiser le const, la syntaxe est comme ceci

static const int a = 10; //at declaration

2) La deuxième façon peut être

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

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

3) Eh bien, si vous ne voulez pas initialiser à la déclaration, alors l'autre façon est de passer par le constructeur, la variable doit être initialisée dans la liste d'initialisation (pas dans le corps du constructeur). Ça doit être comme ça

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};
ravs2627
la source
8
Je pense que cette réponse doit être clarifiée. L'utilisation du mot-clé static pour un membre de classe n'ajoute pas une syntaxe arbitraire pour rendre le compilateur heureux. Cela signifie qu'il existe une seule copie de la variable pour toutes les instances de l'objet, constante ou non. C'est un choix de conception qui doit être considéré avec soin. En bout de ligne, le programmeur peut décider que ce membre de classe constant peut encore varier avec différents objets, même s'il reste constant pendant la durée de vie d'un objet donné.
opetrenko
D'accord .Lorsque nous utilisons de la statique, il n'en crée qu'une seule copie pour tous les objets. Comme vous l'avez mentionné, c'est un choix de conception. En cas de copie unique pour tous les objets 1 et 2 devrait fonctionner. En cas de copie individuelle pour chaque objet, 3 fonctionneraient
ravs2627
Cette réponse suggère un simple changement de syntaxe sans conséquences - alors que la changer pour qu'elle soit statique ne l'est pas.
Isaac Woods
et si vous avez besoin d'utiliser double ou float - est-ce une partie de la norme C ++ 11?
serup
14

Si vous ne souhaitez pas rendre le constmembre de données dans la classe statique, vous pouvez initialiser le constmembre de données à l'aide du constructeur de la classe. Par exemple:

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

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

s'il y a plusieurs constmembres de données dans la classe, vous pouvez utiliser la syntaxe suivante pour initialiser les membres:

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}
GANESH BK
la source
3
Je pense que cela fournit une meilleure réponse que celle qui a été acceptée ....
Ian
1
Merci pour les exemples limpides et la variante montrant une pluralité! Élimination de l'ambiguïté et des recherches / défilement supplémentaires de la part du lecteur!
clearlight
13
  1. Vous pouvez mettre à niveau votre compilateur pour prendre en charge C ++ 11 et votre code fonctionnerait parfaitement.

  2. Utilisez la liste d'initialisation dans le constructeur.

    T1() : t( 100 )
    {
    }
Borisbn
la source
6

Une autre solution est

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

Donc t est initialisé à 100 et il ne peut pas être changé et il est privé.

Musqué
la source
3

Si un membre est un tableau, ce sera un peu plus complexe que la normale:

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
la source
2

Les espaces de noms sont un autre moyen possible:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

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

L'inconvénient est que d'autres classes peuvent également utiliser les constantes si elles incluent le fichier d'en-tête.

Baran
la source
1

C'est la bonne façon de faire. Vous pouvez essayer ce code.

#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 vous utilisez C++10 Compiler or belowalors vous ne pouvez pas initialiser le membre contre au moment de la déclaration. Donc ici, il faut faire constructeur pour initialiser le membre de données const. Il est également indispensable d'utiliser la liste d'initialisation T1():t(100)pour obtenir de la mémoire à l'instant.

Joueur Aziz
la source
0

vous pouvez ajouter staticpour rendre possible l'initialisation de cette variable membre de classe.

static const int i = 100;

Cependant, ce n'est pas toujours une bonne pratique d'utiliser la déclaration de classe interne, car tous les objets instaciés à partir de cette classe partageront la même variable statique qui est stockée dans la mémoire interne en dehors de la mémoire de portée des objets instanciés.

dhokar.w
la source