web-dev-qa-db-fra.com

Pourquoi une fonction membre const peut-elle modifier un membre de données statique?

Dans ce qui suit C++ programme, modifier un membre de données statique à partir d'une fonction const fonctionne correctement:

class A 
{
  public:   
    static int a; // static data member

    void set() const
    {
        a = 10;
    }
};

Mais modifier une membre de données non statique depuis une fonction const ne fonctionne pas:

class A 
{
  public:   
    int a; // non-static data member

    void set() const
    {
        a = 10;
    }
};

Pourquoi une fonction membre const peut-elle modifier un membre data static?

81
msc

C'est la règle, c'est tout. Et pour une bonne raison.

Le qualificatif const d'une fonction membre signifie que vous ne pouvez pas modifier les variables de membre de classe non -mutable non -static.

Pour offrir une certaine rationalisation, le pointeur this dans une fonction membre qualifiée const est un type const et this est intrinsèquement lié à un - instance d'une classe. static les membres ne sont pas liés à une instance de classe. Vous n'avez pas besoin d'une instance pour modifier un membre static: vous pouvez le faire, dans votre cas, en écrivant A::a = 10;.

Donc, dans votre premier cas, pensez à a = 10; comme raccourci pour A::a = 10; et dans le second cas, considérez cela comme un raccourci pour this->a = 10;, qui n'est pas compilable car le type de this est const A*.

94
Bathsheba

Selon la norme C++ (9.2.3.2 Membres de données statiques)

1 Un membre de données statique est ne fait pas partie des sous-objets d'une classe ...

Et (9.2.2.1 Le pointeur this)

1 Dans le corps d'une fonction membre non statique (9.2.1), le mot-clé est une expression prvalue dont la valeur est l'adresse de l'objet pour lequel la fonction est appelée. Le type de ceci dans une fonction membre d'une classe X est X *. Si la fonction membre est déclarée const, son type est const X *, ...

Et enfin (9.2.2 Fonctions membres non statiques)

3 ... si name lookup (3.4) résout le nom dans l'expression id en un membre non typé non statique d'une classe C, et si l'expression id est potentiellement évaluée ou si C est X ou une classe de base de X, l’expression id est transformée en une expression d’accès aux membres de la classe (5.2.5) en utilisant (* this) (9.2.2.1) comme expression postfixe située à gauche de. opérateur.

Donc dans cette définition de classe

class A 
{
  public:   
    static int a; 

    void set() const
    {
        a = 10;
    }
};

le membre de données statique a n'est pas un sous-objet d'un objet du type classe et le pointeur this n'est pas utilisé pour accéder au membre de données statique. Ainsi, toute fonction membre, constante non statique ou non statique, ou une fonction membre statique peut modifier le membre de données car ce n'est pas une constante.

Dans cette définition de classe

class A 
{
  public:   
    int a; 

    void set() const
    {
        a = 10;
    }
};

le membre de données non statique a est un sous-objet d'un objet du type classe. Pour y accéder dans une fonction membre, on utilise soit une syntaxe d'accès membre, de cette syntaxe soit implicite. Vous ne pouvez pas utiliser un pointeur constant this pour modifier le membre de données. Et le pointeur est en effet de type const A * dans la fonction set car la fonction est déclarée avec le qualificatif const. Si la fonction n'avait pas de qualificatif dans ce cas, le membre de données pourrait être modifié.

21
Vlad from Moscow

Le fait est que si une fonction membre d'une classe A est const, le type de this est _const X*_ et empêche ainsi les données non statiques membres d'être altérés (cf, par exemple, norme C++ ):

9.3.2 Le pointeur this [class.this]

Dans le corps d'une fonction membre non statique (9.3), le mot clé this est une expression prvalue dont la valeur est l'adresse de l'objet pour lequel la fonction est appelée. Le type de ceci dans une fonction membre d'une classe X est X *. Si la fonction membre est déclarée const, son type est const X *, ...

Si a est un membre de données non statique, alors _a=10_ est identique à _this->a = 10_, ce qui n'est pas autorisé si le type de this est _const A*_ et a n'a pas été déclaré comme mutable. Ainsi, puisque void set() const rend le type de this étant _const A*_, cet accès n'est pas autorisé.

Si a est un membre de données statique, par contre, alors _a=10_ n'implique pas du tout this; et tant que _static int a_ seul n'a pas été déclaré comme const, l'instruction _a=10_ est autorisée.

13
Stephan Lechner

Le qualificatif const sur un fonction membre signifie que vous ne pouvez pas modifier non-mutable, non-staticmembres de données de classe.

1
Li Kui