为什么一个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数据成员?

这是规则,就是这样。 有很好的理由。

成员函数的const限定符表示不能修改非mutablestatic类成员variables。

通过提供一些合理化的方式,在const限定的成员函数中的this指针是一个consttypes,并且this地与一个类的一个实例相关。 static成员与类实例无关。 你不需要一个实例来修改一个static成员,你可以通过编写A::a = 10;

所以,在你的第一个案例中,想a = 10; 作为A::a = 10;简写A::a = 10; 在第二种情况下,把它看作是this->a = 10;简写this->a = 10; ,这是不可编译的,因为它的types是const A*

根据C ++标准(9.2.3.2静态数据成员)

1静态数据成员不是类的子对象的一部分

和(9.2.2.1这个指针)

1在非静态(9.2.1)成员函数的主体中,关键字this是一个prvalueexpression式,其值是调用该函数的对象的地址。 这个在类X的成员函数中的types是X *。 如果成员函数被声明为const,则其types为const X * ,…

最后(9.2.2非静态成员函数)

3 …如果名称查找(3.4)将idexpression式中的名称parsing为某个类C的非静态非types成员,并且如果可能评估了idexpression式,或者C是X或基类的X,idexpression式被转换成类成员访问expression式(5.2.5),使用(* this) (9.2.2.1)作为左边的后缀expression式。 运营商。

因此在这个类的定义

 class A { public: static int a; void set() const { a = 10; } }; 

静态数据成员a不是类types对象的子对象,并且指针不用于访问静态数据成员。 因此,任何成员函数,非静态常量或非常量,或静态成员函数都可以更改数据成员,因为它不是常量。

在这个类的定义

 class A { public: int a; void set() const { a = 10; } }; 

非静态数据成员a是类types的对象的子对象。 要在成员函数中访问它,可以使用这个语法的成员访问语法。 您可能不会使用一个常量指针来修改数据成员。 而且这个指针的确在函数set有typesconst A * ,因为函数是用限定符const声明的。 如果该函数在这种情况下没有限定符,则数据成员可以被改变。

问题是,如果一个类A的成员函数是const ,那么这个types是const X* ,从而防止非静态数据成员被改变(比如, C ++标准 ):

9.3.2这个指针[class.this]

在非静态(9.3)成员函数的主体中,关键字this是一个prvalueexpression式,其值是调用该函数的对象的地址。 这个在类X的成员函数中的types是X *。 如果成员函数被声明为const,则其types为const X *,…

如果a是一个非静态的数据成员,那么a=10this->a = 10 a=10是一样的,如果这个types是const A*a没有被声明为mutable ,那么这是不允许的。 因此,由于void set() const使得它的types为const A* ,所以这个访问是不允许的。

如果a是一个静态数据成员,相反,那么a=10根本不涉及this ; 只要static int a本身没有被声明为const ,则允许使用语句a=10

成员函数const限定符意味着您不能修改non-mutable non-static 类数据成员