44 votes

Pourquoi les membres const peuvent-ils être modifiés dans un constructeur?

Je suis curieux de savoir pourquoi les membres const peuvent être modifiés dans le constructeur.

Y a-t-il une règle standard dans l'initialisation qui outrepasse la "constance" d'un membre ?

struct Bar {
    const int b = 5; // initialisation par défaut des membres
    Bar(int c):b(c) {}
};

Bar *b = new Bar(2); // Problème : Bar::b est modifié en 2
                     // je m'attendais à une erreur

Des idées ?

0 votes

...comment pourriez-vous attribuer une valeur à une membre const...? De plus, en ce qui concerne les autres commentaires, tellement hors sujet que ça fait mal.

69voto

songyuanyao Points 2265

Ceci n'est pas une modification (ou affectation) mais initialisation. par exemple.

struct Bar {
    const int b = 5; // initialisation (via initialisateur de membre par défaut)
    Bar(int c)
        :b(c)        // initialisation (via liste d'initialisation de membre)
    {
        b = c;       // affectation; ce qui n'est pas autorisé
    }
};

Le membre de donnée const ne peut pas être modifié ou affecté mais il peut (et doit) être initialisé via la liste d'initialisation des membres ou l'initialisateur de membre par défaut.

Si à la fois l'initialisateur de membre par défaut et l'initialisateur de membre sont fournis pour le même membre de donnée, l'initialisateur de membre par défaut sera ignoré. C'est pourquoi b->b est initialisé avec la valeur 2.

Si un membre a un initialisateur de membre par défaut et apparaît également dans la liste d'initialisation des membres dans un constructeur, l'initialisateur de membre par défaut est ignoré.

En revanche, l'initialisateur de membre par défaut prend effet uniquement lorsque le membre de donnée n'est pas spécifié dans la liste d'initialisation des membres. par exemple.

struct Bar {
    const int b = 5;   // initialisation de membre par défaut
    Bar(int c):b(c) {} // b est initialisé avec c
    Bar() {}           // b est initialisé avec 5
};

14 votes

Juste pour développer sur la déclaration que ceci n'est pas une "modification (ou affectation)": Bar(int c):b(c) {} initialise b lorsqu'il est d'abord construit, mais Bar(int c) { b = c; } le lui attribuerait après sa construction avec sa valeur par défaut de 5. C'est ce que const empêche.

17voto

Cássio Renan Points 1605

Ajoutant à la super réponse de songyuanyao, si vous voulez un membre de données const que vous ne pouvez pas initialiser dans un constructeur, vous pouvez rendre le membre static :

struct Bar {
    static const int b = 5; // initialisation du membre static
    Bar(int c)
        :b(c)        // Erreur : le membre de données static ne peut être initialisé que lors de sa définition
    {
        b = c;       // Erreur : b est en lecture seule
    }
};

En C++17, vous pouvez améliorer cela encore plus en le rendant inline :

struct Bar {
    inline static const int b = 5; // initialisation du membre static
    Bar(int c)
        :b(c)        // Erreur : le membre de données static ne peut être initialisé que lors de sa définition
    {
        b = c;       // Erreur : b est en lecture seule
    }
};

De cette façon, vous n'aurez pas de problèmes avec ODR.

2voto

Ajay Points 5320

Lorsque vous faites :

struct Bar {
    const int b = 5; // initialisation par défaut des membres
    ...
};

Vous dites au compilateur de faire ceci avec le constructeur par défaut :

...
Bar() : b(5) 
{}
...

Peu importe si vous avez fourni le constructeur par défaut ou non. Lorsque vous fournissez le constructeur par défaut et l'assignation initiale, vous remplacez le code d'assignation par défaut du compilateur (c'est-à-dire b(5)). L'initialisation/assignation par défaut à la déclaration est utile lorsque vous avez plusieurs constructeurs et que vous pouvez ou non affecter les membres constants dans tous les constructeurs :

...
Bar() = default; // b=5
Bar(int x) : b(x) // b=x
Bar(double y) : /*autre init, mais pas b*/  // b=5
...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X