【问题标题】:Why can a const member function modify a static data member?为什么 const 成员函数可以修改静态数据成员?
【发布时间】:2017-10-11 16:41:08
【问题描述】:

在以下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 数据成员?

【问题讨论】:

  • 如果您能告诉我们您正在使用哪个平台和编译器会很有帮助?因此,我们可以确定该行为是否是与您的特定设置相关的错误,或者该行为是否确实正确并且只需要解释。
  • @AlexZywicki G++ 编译器在 Linux 平台上。
  • 不需要。这是有意的,所有 C++ 编译器都必须支持它。但是为什么像这样的好问题不再被赞成了呢?
  • 这是一个骗子,但由于更好的 MCVE,它比另一个写得更好,所以我用它作为目标。
  • 这里的动机是const意味着一个对象的成员函数不能修改那个对象。它可以修改同一类的其他对象,或与该类关联的static 数据,而不是它的任何特定实例。 (或 mutable 数据成员,它们被创建为该规则的例外。)

标签: c++ function c++11 static constants


【解决方案1】:

这是规则,仅此而已。并且有充分的理由。

成员函数上的const 限定符意味着您不能修改非mutablestatic 类成员变量。

通过提供一些合理化,const 限定成员函数中的this 指针是const 类型,而this 本质上与类的实例相关. static 成员与类实例无关。您不需要实例来修改 static 成员:在您的情况下,您可以通过编写 A::a = 10; 来做到这一点。

所以,在第一种情况下,将a = 10; 视为A::a = 10; 的简写,在第二种情况下,将其视为this->a = 10; 的简写,因为this 的类型是@,所以它不可编译987654335@.

【讨论】:

  • 这里只是一个小错误:由于您无法重新分配 this 指针,因此在 const 的情况下它将是 const A* const 类型。
  • @TaylorHansen this 是指针类型的纯右值。非类类型的纯右值永远不是 cv 限定的。
【解决方案2】:

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

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

And (9.2.2.1 this 指针)

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

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

3 ... 如果名称查找 (3.4) 将 id 表达式中的名称解析为 某个类 C 的非静态非类型成员,并且如果 id-expression 可能被评估或 C 是​​ X 或 X 的基类, id-expression 被转换为类成员访问表达式 (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 来修改数据成员。并且指针 this 确实在函数set 中具有类型const A *,因为该函数是用限定符const 声明的。如果在这种情况下函数没有限定符,则可以更改数据成员。

【讨论】:

    【解决方案3】:

    问题是,如果类A 的成员函数是const,那么this 的类型是const X*,从而防止非静态数据成员被更改(参见,对于例如C++ standard):

    9.3.2 this 指针[class.this]

    在非静态 (9.3) 成员函数的主体中,关键字 this 是纯右值表达式,其 value 是调用函数的对象的地址。 类 X 的成员函数中 this 的类型是 X*。如果 成员函数声明为 const,this 的类型为 const X*, ...

    如果a是一个非静态数据成员,那么a=10this->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限定符意味着您不能修改non-mutablenon-static类数据成员

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-06
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 2017-01-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多