Подтвердить что ты не робот

Почему функция const-члена может изменять статический элемент данных?

В следующей программе C++ изменение функции статического элемента данных из функции const работает нормально:

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

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

Но изменение нестатического элемента данных из функции const не работает:

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

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

Почему функция члена const изменяет член данных static?

4b9b3361

Ответ 1

Это правило, что все. И не зря.

Квалификатор const для функции-члена означает, что вы не можете изменять переменные-члены класса mutable не static.

В качестве предложения некоторой рационализации указатель this в const квалифицированной функции-члена является типом const, а this неотъемлемо связан с экземпляром класса. Члены static не связаны с экземпляром класса. Вам не нужен экземпляр для изменения члена static: вы можете сделать это в своем случае, написав A::a = 10;.

Итак, в вашем первом случае подумайте о a = 10; как сокращении для A::a = 10;, а во втором случае подумайте об этом как сокращении для this->a = 10;, который не компилируется, так как тип this равен const A*.

Ответ 2

В соответствии со стандартом С++ (9.2.3.2 статические элементы данных)

1 Статический член данных не является частью подобъектов класса...

И (9.2.2.1 Этот указатель)

1 В теле нестатической (9.2.1) функции-члена ключевое слово это выражение prvalue, значением которого является адрес объекта для которого вызывается функция. Тип этого в члене функция класса X есть X *. Если объявлена ​​функция-член const, тип этого - const X *,...

И наконец (9.2.2 Нестатические функции-члены)

3... если поиск имени (3.4) разрешает имя в id-выражении на нестатический член не-типа некоторого класса C, и если либо id-выражение потенциально оценивается или C является X или базовым классом X, выражение id преобразуется в выражение доступа к члену класса (5.2.5), используя (* this) (9.2.2.1) в качестве постфиксного выражения для слева от. Оператор.

Таким образом, в этом определении класса

class A 
{
  public:   
    static int a; 

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

статический член данных a не является подобъектом объекта типа класса, а указатель this не используется для доступа к статическому элементу данных. Таким образом, любая функция-член, нестатическая константа или не константа или статическая функция-член может изменять элемент данных, потому что это не константа.

В этом определении класса

class A 
{
  public:   
    int a; 

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

нестатический член данных a является подобъектом объекта типа класса. Для доступа к ней в функции-члене используется либо синтаксис доступа к членству в этом синтаксисе. Вы не можете использовать константный указатель this для изменения элемента данных. И указатель действительно имеет тип const A * внутри функции set, потому что функция объявлена ​​с помощью квалификатора const. Если функция не имела квалификатора, в этом случае элемент данных мог быть изменен.

Ответ 3

Дело в том, что если функция-член класса A равна const, то тип this равен const X* и тем самым предотвращает изменение нестатических членов данных (cf, for Например, С++ standard):

9.3.2 Этот указатель [class.this]

В теле нестатической (9.3) функции-члена ключевым словом является выражение prvalue, value - адрес объекта, для которого вызывается функция. Тип этого в членной функции класса X есть X *. Если член-функция объявлена ​​const, тип которой - const X *,...

Если A - нестатический член данных, то a=10 совпадает с this->a = 10, что недопустимо, если тип this равен const A* и A не был объявлен как mutable. Таким образом, поскольку void set() const делает тип this const A*, этот доступ не разрешен.

Если A является элементом статических данных, то, напротив, a=10 вообще не включает this; и пока static int a сам по себе не был объявлен как const, оператор a=10 разрешен.

Ответ 4

Квалификатор const в функции member означает, что вы не можете изменять non-mutable, non-static члены данных класса.