以下では C++
プログラムは、const
関数から静的データメンバーを修正すると正常に動作します。
class A
{
public:
static int a; // static data member
void set() const
{
a = 10;
}
};
ただし、const
関数から非静的データメンバーを変更しても機能しません。
class A
{
public:
int a; // non-static data member
void set() const
{
a = 10;
}
};
なぜconst
メンバー関数がstatic
データメンバーを変更できるのですか?
それがルールです、それがすべてです。そして、十分な理由があります。
メンバー関数のconst
修飾子は、非mutable
非static
クラスメンバー変数を変更できないことを意味します。
何らかの合理化を提供するために、this
修飾メンバー関数のconst
ポインターはconst
型であり、this
は本質的にクラスのインスタンス。 static
メンバーは、クラスインスタンスに関連していません。 static
メンバーを変更するためにインスタンスは必要ありません:あなたの場合、A::a = 10;
と書くことでそれを行うことができます。
したがって、最初のケースでは、a = 10;
をA::a = 10;
の短縮形と考え、2番目のケースでは、this->a = 10;
の短縮形と考えてください。これは、this
はconst A*
です。
C++標準(9.2.3.2静的データメンバー)に準拠
1静的データメンバーはクラスのサブオブジェクトの一部ではない ...
そして(9.2.2.1 thisポインター)
1非静的(9.2.1)メンバー関数の本体では、キーワードthisは値が関数が呼び出されるオブジェクトのアドレスであるprvalue式です。クラスXのメンバー関数のこの型はX *です。 メンバー関数がconstとして宣言されている場合、この型はconst X *です、...
そして最後に(9.2.2非静的メンバー関数)
3 ...名前ルックアップ(3.4)がid-expressionの名前を何らかのクラスCの非静的非型メンバーに解決し、id-expressionが潜在的に評価されるか、CがXまたは基本クラスである場合Xの場合、id-expressionは、(* this)(9.2.2.1)を左側のpostfix-expressionとして使用して、クラスメンバーアクセス式(5.2.5)に変換されます。オペレーター。
したがって、このクラス定義では
class A
{
public:
static int a;
void set() const
{
a = 10;
}
};
静的データメンバーa
はクラス型のオブジェクトのサブオブジェクトではなく、ポインターthis
は静的データメンバーへのアクセスには使用されません。したがって、非静的定数または非定数、または静的メンバー関数は、定数ではないため、データメンバーを変更できます。
このクラス定義では
class A
{
public:
int a;
void set() const
{
a = 10;
}
};
非静的データメンバa
は、クラスタイプのオブジェクトのサブオブジェクトです。メンバー関数でアクセスするには、この構文のメンバーアクセス構文が暗黙的に使用されます。定数ポインターthis
を使用してデータメンバーを変更することはできません。関数は修飾子set
で宣言されているため、これは実際、関数const
内でconst A *
型を持っています。この場合、関数に修飾子がない場合、データメンバーを変更できます。
問題は、クラスA
のメンバー関数がconst
である場合、this
の型はconst X*
であるため、非静的データメンバーが変更されるのを防ぐことです。 (たとえば、 C++標準 を参照):
9.3.2 thisポインター[class.this]
非静的(9.3)メンバー関数の本文では、キーワードthisは、値が関数が呼び出されるオブジェクトのアドレスであるprvalue式です。クラスXのメンバー関数のこの型はX *です。メンバー関数がconstとして宣言されている場合、この型はconst X *、...
a
が非静的データメンバーの場合、a=10
はthis->a = 10
と同じです。this
の型がconst A*
であり、a
が宣言されていない場合は許可されませんmutable
として。したがって、void set() const
はthis
の型をconst A*
にするため、このアクセスは許可されません。
対照的に、a
が静的データメンバーである場合、a=10
はthis
をまったく含みません。また、static int a
自体がconst
として宣言されていない限り、ステートメントa=10
は許可されます。
メンバー関数のconst
修飾子は、non-mutable
、non-static
クラスデータメンバーを変更できないことを意味します。