为什么一个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
限定符表示不能修改非mutable
非static
类成员variables。
通过提供一些合理化的方式,在const
限定的成员函数中的this
指针是一个const
types,并且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=10
与this->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
类数据成员 。