C++:类变量如何修改?

C++ : how does class variable get modified?

提问人:user137263 提问时间:4/22/2013 最后编辑:Alex Chamberlainuser137263 更新时间:4/22/2013 访问量:338

问:

从有关 const 函数的 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
}

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

C++ OOP 作用域 按值传递

评论

0赞 Some programmer dude 4/22/2013
month因为分配而被“修改”了?它甚至在评论中这样说:“修改数据成员”setMonth

答:

1赞 Lefteris E 4/22/2013 #1

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

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

mn 作为参数传入。这样,无论您作为参数放置的任何内容,都将分配给类的 month 成员变量。

1赞 Alex Chamberlain 4/22/2013 #2

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

重写可能更清楚,setMonth

void Date::setMonth( int mn )
{
   this->month = mn;          // Modifies data member
}
5赞 Andy Prowl 4/22/2013 #3

此外,函数如何知道月份变量以在不传入的情况下对其进行修改?

成员函数(如 )隐式接收指向调用它们的类型(在本例中)的对象的指针。对于限定为 的成员函数,指针是指向 的指针,它不允许修改所指向对象的状态。setMonth()thisDateconstthisconst

事实上,以下几点:

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
}

重要:隐式指针实际上是一个指针,指向调用成员函数的对象是否具有 -qualified 类型。thisconstconst

这就是为什么你不能在类型 -qualified 的对象上调用本身不限定的成员函数:对象的状态永远不应该被改变,非函数也不承诺永远不会改变它。constconstconstconst

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

评论

0赞 user137263 4/22/2013
很好的答案。这个指针的隐含性质让我感到困惑。
0赞 Agentlien 4/22/2013
这是一个非常清楚的解释。内容丰富,直截了当。+1
0赞 Andy Prowl 4/22/2013
@Agentlien:谢谢,很高兴你很感激
0赞 bash.d 4/22/2013 #4

通过定义对象,可以向编译器保证对象的状态不会改变。它保持状态,就像它被创建一样。
调用方法时,无论是按引用还是按值传递,您都在更改对象的状态。
constsetMonth()

void Date::setMonth( int mn )
{
   month = mn;          // Modifies data member <--- Trying to modify the whole object by changing a part of it
}
1赞 Agentlien 4/22/2013 #5

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

BirthDate.getMonth();

这是可以的,因为 while 是 ,被声明,因此保证它不会改变它。BirthDateconst DategetMonthconst

这不起作用的原因:

BirthDate.setMonth( 4 );

是 没有 声明 的 ,这意味着它不 保证 它 不会 改变 , 即 它 被 调用 的 对象 。setMonthconstBirthDate

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

至于程序如何知道函数会修改对象:它没有。但是你不能调用一个未在对象上声明的函数,该函数是 .此外,尝试修改声明的函数中的(非)成员变量将产生编译器错误。因此,编译器确保您不会违背承诺。(虽然自然而然地,有一些邪恶的符合标准的方式偷偷地违背了这个承诺。但这是不道德和危险的。constconstmutableconst

0赞 Pixelchemist 4/22/2013 #6

MyDate是类的对象。 每个对象都有自己的对象,自从它被声明以来,它是已知的。(即使从类之外,您也知道它包含一个,但您无法访问它,因为它是私有的。 您还可以使用指针(它是每个类中指向自己的内存位置的指针)。DateDateint monthDateint monththis

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

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