【问题标题】:C++ : how does class variable get modified?C++:如何修改类变量?
【发布时间】:2013-04-15 04:48:22
【问题描述】:

来自关于const functions的MSDN页面

代码:

    // constant_member_function.cpp
class Date
{
public:
   Date( int mn, int dy, int yr );
   int getMonth() const;     // A read-only function
   void setMonth( int mn );   // A write function; can't be const
private:
   int month;
};

int Date::getMonth() const
{
   return month;        // Doesn't modify anything
}
void Date::setMonth( int mn )
{
   month = mn;          // Modifies data member
}
int main()
{
   Date MyDate( 7, 4, 1998 );
   const Date BirthDate( 1, 18, 1953 );
   MyDate.setMonth( 4 );    // Okay
   BirthDate.getMonth();    // Okay
   BirthDate.setMonth( 4 ); // C2662 Error
}

但是month 是如何在setMonth 函数中被修改的呢?该函数按值传递并且不返回任何内容。此外,该函数如何知道月份变量以在不传入的情况下对其进行修改?

【问题讨论】:

  • month 因为分配而在setMonth 中得到“修改”?它甚至在评论中这样说:“修改数据成员”

标签: c++ oop scope pass-by-value


【解决方案1】:

setMonth 是 Date 类的成员方法,因此可以看到 Date 类的所有成员变量

void Date::setMonth( int mn )
{
   month = mn;          // Modifies data member
}

mn 作为参数传入。这样,无论您作为参数输入什么,都将分配给该类的月份成员变量。

【讨论】:

    【解决方案2】:

    setMonth 是一个成员函数。因此,它有一个隐含的this 指针,指向它正在操作的对象。也就是说,特定对象的每个成员变量都在范围内,并且(非常量)成员函数可以修改它们。

    重写setMonth可能会更清晰,

    void Date::setMonth( int mn )
    {
       this->month = mn;          // Modifies data member
    }
    

    【讨论】:

      【解决方案3】:

      此外,该函数如何知道月份变量来修改它而不传递它?

      成员函数(如setMonth())隐式接收到this 类型的对象的指针(在这种情况下)Date 它们被调用。对于限定为const 的成员函数,this 指针是指向const 的指针,它不允许您修改指向对象的状态。

      其实如下:

      void Date::setMonth( int mn )
      {
          month = mn;          // Modifies data member
      }
      

      等价于:

      void Date::setMonth( int mn )
      {
          this->month = mn;          // Modifies data member
      //  ^^^^^^
      //  "this" is a pointer to an object of type Date (i.e. Date*),
      //  and that is the object on which setMonth() is invoked
      }
      

      所有其他成员函数也是如此,所以:

      int Date::getMonth() const
      {
          return month;        // Doesn't modify anything
      }
      

      相当于:

      int Date::getMonth() const
      //                   ^^^^^ Means the implicit "this" pointer is const
      {
          return this->month;        // Doesn't modify anything
      //         ^^^^^^
      //         Here, "this" is a pointer to a CONST Date object (i.e. Date const*),
      //         and that is the object on which getMonth() is invoked
      }
      

      重要提示:如果调用成员函数的对象具有const 限定类型,则隐式this 指针实际上是指向const 的指针。

      这就是为什么你不能在一个类型为 const-qualified 的对象上调用本身不是 const-qualified 的成员函数:a 的状态 const 对象永远不应该被改变,非const 函数不保证永远不会改变它。

      因此,编译器将通过引发错误来阻止您对const 限定类型(例如const Date)的对象调用非const 函数(例如Date::setMonth())。

      【讨论】:

      • 优秀的答案。 this 指针的隐含性质让我感到困惑。
      • @user137263:很高兴它有帮助:)
      • 这是一个非常清晰的解释。内容丰富且直截了当。 +1
      • @Agentlien:谢谢,很高兴您能欣赏它
      【解决方案4】:

      通过将您的对象定义为const,您可以向编译器保证对象的状态不会改变。它保持创建时的状态。
      当调用你的方法setMonth()时,你正在改变对象的状态,不管你是通过引用还是通过值。

      void Date::setMonth( int mn )
      {
         month = mn;          // Modifies data member <--- Trying to modify the whole object by changing a part of it
      }
      

      【讨论】:

        【解决方案5】:

        答案是const 声明的函数表示该函数不会修改调用该函数的对象。也就是说,如果你这样做:

        BirthDate.getMonth();
        

        这没关系,因为虽然BirthDateconst Date,但getMonth 被声明为const,因此保证它不会改变它。

        这不起作用的原因:

        BirthDate.setMonth( 4 );
        

        setMonth 没有声明const,这意味着它不保证它不会改变BirthDate,即调用它的对象。

        改变的不是输入参数,而是调用函数的对象。在setMonth 的情况下,修改的是Date 实例中的month 变量。

        关于程序如何知道函数将修改对象:它不知道。但是您不能在 const 的对象上调用未声明为 const 的函数。此外,尝试在声明为const 的函数中修改(非mutable)成员变量会导致编译器错误。因此,编译器确保您不会违背承诺。 (当然,有一些邪恶的符合标准的方式偷偷地违背这个承诺。但这只是不道德和危险的。)

        【讨论】:

          【解决方案6】:

          MyDateDate 类的对象。 每个Date 对象都有自己的int month,自从它被声明后就知道了。 (即使在课堂之外,您也知道Date 包含int month,但您无法访问它,因为它是私有的。 您还可以使用this 指针(它是每个类中可用的指针,指向自己的内存位置)。

          setMonth 的代码隐式执行以下操作:

          void Date::setMonth( int mn )
          {
             (*this).month = mn;          // Modifies data member
          }
          

          【讨论】:

            猜你喜欢
            • 2011-12-10
            • 1970-01-01
            • 2014-05-19
            • 1970-01-01
            • 1970-01-01
            • 2018-01-08
            • 2020-09-10
            • 2013-02-22
            • 1970-01-01
            相关资源
            最近更新 更多