コンパイラはどのメンバー関数が変異するかをどのように決定しますか?
-
22-07-2019 - |
質問
興味のある投稿へのコメント:
私も。また、アクセサー/ミューテーターに同じ名前を付けます。
これについて疑問に思っていました。同じ名前のミューテーターの代わりに、常に setBar(int bar)
を使用していたからです。知りたい:コンパイラはconst識別子に基づいて実行時に何を変更するかを決定できますか、またはパラメータがあるため同じ関数名を使用できますか?
これで問題なくコンパイルされます:
class Foo
{
int bar_;
public:
int bar() { return bar_; }
void bar(int bar) { bar_ = bar; }
}
またはこれを実行する必要があります(とにかくこれを実行する必要があることを理解しています、これで私と一緒に実行してください):
int bar() const { return bar_; }
どちらがどれなのかわかりません。定数の正確性は重要です。そのため、1つは変化し、もう1つは変化しないため、コンパイラにオーバーロードに反対してもらいたいと思います。
なぜこのように機能するのですか?
解決
コンパイラが最初に確認するのは、関数に渡すパラメーターの数とタイプです。これにより、 const
-nessを確認する前に、 bar
のオーバーロードが解決されます。
bar()
を const
としてマークしなかった場合、コンパイラは bar()を初めて呼び出そうとしたときにこれを通知しますオブジェクトの
const
インスタンスのcode>。
他のヒント
コンパイラは、実際にはオブジェクトを変更しない非constメンバ関数の作成を妨げません。これはconst-correctnessの違反ではなく、const参照を介してオブジェクトが変更されないことを保証するだけです。ここでの原則は、constは関数が変化しない可能性があることを示し、non-constは関数が必要に応じて自由に変化できることを意味します。変異することを約束する方法はなく、コンパイラにそれを強制するようにさせる方法はありません。これは、呼び出し側にとって有用であるにはあまりにも曖昧な保証になると思います。
Gregが言うように、constオブジェクトで非constメンバ関数を呼び出そうとすると、コンパイラは反対します(繰り返しますが、実際に変化するかどうかは関係ありません。唯一の重要なことは、constが宣言されているかどうかです)
理解を容易にするために、非constメソッドがそのオブジェクトに対して呼び出された場合、コンパイラはオブジェクトが変更されると仮定することを考慮してください。
constメソッドで、データメンバーの1つに対して非constメソッドを呼び出すか、クラスの別の非constメソッドを呼び出すと、コンパイラーはエラーを通知します。
演算子もメソッドと見なすことができます(一部の演算子はメソッドとしてではなく、単純化のためにフレンド関数として定義できます...)。たとえば、代入演算子(operator =)はデフォルトでは非定数です。つまり、次のようなことを行う場合
void MyClass::MyConstMethod() const
{
classMember = value;
}
コンパイラは、constメソッド内でconstオブジェクトであるclassMemberの代入演算子を呼び出したと見なします。 operator =はconstではないため、コンパイラエラーが報告されます。