Почему функция 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
?
Ответы
Ответ 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
члены данных класса.