уп — C ++: как переменная класса изменяется?

Со страницы 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 функционировать? Функция проходит по значению и ничего не возвращает. Кроме того, как функция узнает о переменной месяца, чтобы изменить ее без передачи?

-1

Решение

Кроме того, как функция узнает о переменной месяца, чтобы изменить ее без передачи?

Функции-члены (лайк 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
}

ВАЖНЫЙ: Неявный this указатель на самом деле указатель на const если объект, для которого вызывается функция-член, имеет constквалифицированный тип.

Вот почему вы не можете вызвать функцию-член, которая не является самой const-квалифицированный на объекте, чей тип является const-qualified: состояние const объект никогда не должен быть изменен, и неconst Функция не обещает никогда ее не изменять.

Следовательно, компилятор не позволит вам вызыватьconst функция (например, Date::setMonth()) на объекте constквалифицированный тип (например, const Date) подняв ошибку.

5

Другие решения

setMonth является методом-членом класса Date и, следовательно, может видеть все переменные-члены класса Date

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

Миннесота передается в качестве аргумента. Таким образом, все, что вы указали в качестве аргумента, будет присвоено переменной-члену месяца класса.

1

setMonth является функцией-членом. Следовательно, он имеет неявное this указатель на объект, над которым он работает. То есть каждая из переменных-членов конкретного объекта находится в области видимости, и (неконстантные) функции-члены могут изменять их.

Может быть понятнее переписать setMonth,

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

Ответ в том, что const объявленная функция говорит, что функция не будет изменять объект, для которого вызывается функция. То есть, если вы делаете:

BirthDate.getMonth();

Это нормально, потому что пока BirthDate это const Date, getMonth объявлен constи, таким образом, гарантирует, что это не изменит его.

Причина, по которой это не работает:

BirthDate.setMonth( 4 );

в том, что setMonth не объявлено constЭто означает, что он не оставляет никаких гарантий, что он не изменится. BirthDateобъект, к которому он относится.

Изменяются не входные параметры, а объект, для которого вызывается функция. В случае setMonth, это month переменная в вашем Date экземпляр, который модифицируется.

Относительно того, как программа знает, что функция будет изменять объект: это не так. Но вы не можете вызвать функцию, которая не объявлена const на объекте, который const, Кроме того, пытаясь изменить (неmutable) переменная-член в объявленной функции const выдаст вам ошибки компилятора. Следовательно, компилятор гарантирует, что вы не нарушите свое обещание. (Хотя, естественно, существуют злые, соответствующие стандартам, способы скрытно нарушать это обещание. Но это просто аморально и опасно.)

1

Определяя ваш объект как const вы заверяете компилятор, что состояние объекта не изменится. Он остается в состоянии, как будто он был создан.
При вызове вашего метода setMonth()Вы изменяете состояние объекта, независимо от того, передаете ли вы по ссылке или по значению.

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

MyDate является объектом Date учебный класс.
каждый Date объект имеет свой int month который известен, так как он объявлен. (Даже вне класса вы знаете, что Date содержит int month но вы не можете получить к нему доступ, так как это личное.
Вы также можете использовать this указатель (который является указателем, доступным в каждом классе, указывающим на его собственную область памяти).

Код setMonth неявно делает следующее:

void Date::setMonth( int mn )
{
(*this).month = mn;          // Modifies data member
}
0
По вопросам рекламы [email protected]