Question

From the MSDN page concerning const functions

The code:

    // 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
}

But how does month get modified in the setMonth function? The function is passing by value and returning nothing. Furthermore, how would the function even know about the month variable to modify it without it being passed in?

Was it helpful?

Solution

Furthermore, how would the function even know about the month variable to modify it without it being passed in?

Member functions (like setMonth()) implicitly receive a this pointer to the object of type (in this case) Date they are invoked on. For member functions qualified as const, the this pointer is a pointer to const, which won't allow you to modify the state of the pointed object.

In fact, the following:

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

Is equivalent to the following:

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
}

Same story for all other member functions, so:

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

Is equivalent to:

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
}

IMPORTANT: The implicit this pointer is actually a pointer to const if the object on which the member function is invoked has a const-qualified type.

This is why you cannot invoke a member function which is not itself const-qualified on an object whose type is const-qualified: the state of a const object should never be altered, and a non-const function does not promise to never alter it.

Therefore, the compiler will prevent you from calling a non-const function (e.g. Date::setMonth()) on an object of a const-qualified type (e.g. const Date) by raising an error.

OTHER TIPS

setMonth is a member method of the Date class, and hence can see all member variables of the Date class

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

mn is passed in as an argument. In this way whatever you have put as the argument, will be assigned to the month member variable of the class.

setMonth is a member function. Therefore, it has an implicit this pointer to the object it is operating on. That is, each of the member variables of a particular object are in scope and the (non-const) member functions can modify them.

It may be clearer to rewrite setMonth,

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

The answer is that a const declared function says that the function will not modify the object on which the function is called. That is, if you do:

BirthDate.getMonth();

This is OK, because while BirthDate is a const Date, getMonth is declared const, and thus guarantees it won't change it.

The reason this doesn't work:

BirthDate.setMonth( 4 );

is that setMonth is not declared const, which means it does not leave any guarantee that it will not change BirthDate, i.e. the object on which it is called.

It is not the input parameters which get changed, it is the object on which the function is called. In the case of setMonth, it is the month variable in your Date instance which gets modified.

As to how the program knows that the function will modify an object: it doesn't. But you cannot call a function which is not declared const on an object which is const. Also, trying to modify a (non-mutable) member variable in a function declared const will give you compiler errors. Hence, the compiler ensures that you do not break your promise. (Though naturally, there are evil standard-conforming ways of sneakily breaking this promise. But that's just immoral and dangerous.)

By defining your object as const you are assuring the compiler that the state of the object will not change. It stays in the state like it was created.
When calling your method setMonth(), you are changing the state of the object, no matter if you pass by reference or by value.

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

MyDate is an object of the Date class. Each Date object has its own int month which is known since it is declared. (Even from outside the class you know that Date contains an int month but you cannot access it, since it is private. You could also use the this pointer (which is a pointer available within each class pointing to ist own memory location).

The code of setMonth is implicitly doing the following:

void Date::setMonth( int mn )
{
   (*this).month = mn;          // Modifies data member
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top