-1

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
}

しかし、関数内でどのようmonthに変更されるのでしょうか? setMonth関数は値渡しで、何も返しません。さらに、月の変数を渡されずに変更するために、関数はどのようにして月の変数を知るのでしょうか?

4

6 に答える 6

5

さらに、月の変数を渡されずに変更するために、関数はどのようにして月の変数を知るのでしょうか?

メンバー関数( など)は、呼び出される型 (この場合) のオブジェクトへのポインターを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
}

重要:メンバ関数が呼び出されるオブジェクトが修飾された型を持つ場合、暗黙的なthisポインタは実際にはへのポインタです。constconst

constこれが、型 -qualified であるオブジェクトに対して、それ自体が-qualifiedではないメンバー関数を呼び出すことができない理由ですconst:オブジェクトの状態は const 決して変更されるべきではありconstません。

したがって、コンパイラは、エラーを発生させることにより、修飾された型 ( など)のオブジェクトで非const関数 ( など) を呼び出すことを防ぎます。Date::setMonth()constconst Date

于 2013-04-22T10:15:02.453 に答える
1

答えは、const宣言された関数は、関数が呼び出されたオブジェクトを関数が変更しないことを示しているということです。つまり、次の場合です。

BirthDate.getMonth();

whileBirthDateは でありconst DategetMonthが宣言constされているため、変更されないことが保証されているため、これで問題ありません。

これが機能しない理由:

BirthDate.setMonth( 4 );

それsetMonthは宣言されていないということです。つまり、それが呼び出されたオブジェクトがconst変更されないという保証はありません。BirthDate

変更されるのは入力パラメータではなく、関数が呼び出されるオブジェクトです。の場合、変更されるのはインスタンス内setMonthmonth変数です。Date

関数がオブジェクトを変更することをプログラムがどのように認識するかについては、そうではありません。constただし、 であるオブジェクトで宣言されていない関数を呼び出すことはできませんconstmutableまた、宣言された関数内の (非) メンバー変数を変更しようとすると、constコンパイラ エラーが発生します。したがって、コンパイラは、約束を破らないことを保証します。(当然のことながら、この約束をこっそり破る、標準に準拠した邪悪な方法があります。しかし、それは単に不道徳で危険です。)

于 2013-04-22T10:16:57.870 に答える
1

setMonth は Date クラスのメンバー メソッドであるため、Date クラスのすべてのメンバー変数を参照できます。

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

mnが引数として渡されます。このようにして、引数として入力したものはすべて、クラスの month メンバー変数に割り当てられます。

于 2013-04-22T10:13:24.497 に答える
1

setMonthメンバー関数です。したがって、操作対象のオブジェクトへの暗黙的なthisポインターがあります。つまり、特定のオブジェクトの各メンバー変数はスコープ内にあり、(非 const) メンバー関数はそれらを変更できます。

書き直した方がわかりやすいかもしれませんがsetMonth

void Date::setMonth( int mn )
{
   this->month = mn;          // Modifies data member
}
于 2013-04-22T10:14:22.640 に答える
0

オブジェクトを定義することによりconst、オブジェクトの状態が変わらないことをコンパイラーに保証します。作ったままの状態を保っています。
method を呼び出すときsetMonth()は、参照渡しか値渡しかに関係なく、オブジェクトの状態を変更しています。

void Date::setMonth( int mn )
{
   month = mn;          // Modifies data member <--- Trying to modify the whole object by changing a part of it
}
于 2013-04-22T10:15:17.720 に答える
0

MyDateDateクラスのオブジェクトです。各オブジェクトには、宣言されているため既知Dateの独自のオブジェクトがあります。int month(クラスの外部からでも、がDate含まれていることがわかってint monthいますが、プライベートであるためアクセスできません。thisポインターを使用することもできます(これは、各クラス内で使用可能なポインターであり、 ist 独自のメモリ位置を指します)。

setMonth のコードは、暗黙的に次のことを行っています。

void Date::setMonth( int mn )
{
   (*this).month = mn;          // Modifies data member
}
于 2013-04-22T10:17:18.310 に答える