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?


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.


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
}

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

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){}

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 )
    {
    }

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é.


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) {}
};

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.


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.


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.