C++におけるconst
オペレーターの理解
C++を扱っていると、メソッド宣言にconst
キーワードが付けられたクラスに出くわすことがあります。これは、実際に何を意味するのか疑問を感じることがあるため、混乱を招くことがあります。この投稿では、例を用いてC++メソッドにおけるconst
オペレーターの役割を明確にし、その重要性と機能を説明します。
メソッド宣言におけるconst
の意味とは?
C++クラスで、次のようにconst
キーワードを使ってメソッドを宣言すると:
class A {
public:
void Foo() const;
};
これは、そのメソッドがオブジェクトの状態を変更できないことを示します。つまり、この関数はコンパイラに対して、クラスのメンバー変数を変更しないことを約束しており、オブジェクトを扱う際の安全性と明確性を高めることができます。
const
関数のルール
- 契約上の義務: 関数を
const
で宣言することで、この関数はメンバー変数の値を変更せず、非const
メンバー関数を呼び出さないことを示しています。 - constオブジェクトとの互換性:
const
関数は、const
として宣言されたオブジェクトに対して呼び出すことができます。たとえば、以下のように準備した場合:
const A *A1 = new A();
A1->Foo(); // OK
このコードは、Foo()
がオブジェクトA1
の状態を変更しないため、問題なく動作します。
非const
関数の必要性
次の例を考えてみましょう:
class A {
public:
void Foo() const; // Const関数
void Moo(); // 非const関数
private:
int m_nState; // 状態を表す整数
int GetState() const { return m_nState; }
void SetState(int val) { m_nState = val; }
};
const A *A1 = new A();
A *A2 = new A();
A1->Foo(); // OK
A1->Moo(); // エラー - constオブジェクトインスタンスで非const関数を呼び出すことはできません
例での使用
A1
に対してFoo()
を呼び出すことは許可されます。なぜなら、これはconst
メソッドであるからです。Moo()
、すなわち非const
メソッドを呼び出そうとすると、オブジェクトの状態を変更するためエラーが発生します。
mutable
の役割
時には、周囲のオブジェクトが論理的にconst
と見なされる場合でも、特定のメンバー変数を変更可能にしたいことがあります。そのような場合、mutable
キーワードを使って変数を宣言できます。例えば:
class A {
private:
mutable int m_nState; // これはconst関数内で変更可能です
};
これにより、m_nState
メンバーは変更可能となり、関数をconst
として宣言できるようになります。基本的には、コンパイラにこの変数の変更を無視させ、内部状態の変更を管理しながら一貫したインターフェースを維持できるように指示します。
重要点のまとめ
const
メソッドはメンバー変数を変更しないことを約束します。const
オブジェクトにconst
メソッドを呼び出すことができます。const
オブジェクトに非const
メソッドを呼び出すことはできません。const
関数内で変更が必要なメンバーにはmutable
を使用します。
結論
C++におけるconst
オペレーターの理解は、安全で効果的なコードを書くために不可欠であり、特に変更してはいけないオブジェクトを管理する際に重要です。これらのルールに従うことで、C++アプリケーションにおいてより保守可能で予測可能なコードを作成できます。const
キーワードは偶発的な変更を防ぐだけでなく、後でコードを読む誰にとっても意図を明確に文書化します。