C++の基礎 : const 修飾子
const 修飾子
C++ 言語には、定数を表現するための const 修飾子が用意されています。ここでは const 修飾子のさまざまな使い方について説明します。
const 修飾子を使う目的は、コンパイラによる最適化を促進するためと、プログラムの意味をより明確にすることです。
const 変数
変数の宣言に const をつけることで、その変数の値が書き換えられないようにできます。
const SIntN max_foods = 120; max_foods = 130; // コンパイル エラー
const 引数
関数の引数に const を指定すると、その関数の中では値を書き換えることができなくなります。これはクラスのメンバ関数であっても同じです。
const 引数は参照引数と共に使われることが多いです。参照引数は実際にはポインタであるため、大きな構造体やクラスを引数に渡すときにも効率のよい方法ですが、const をつけない参照渡しであれば、関数により中身を書き換えられる可能性があることになります。参照渡しに const 修飾子をつけることにより、引数の中身を書き換えないことを宣言することができます。
class Color { public: UInt08 r, g, b; }; UInt08 Brightness(const Color& color) { return MAX(color.r MAX(color.g, color.b)); }
この Brightness() 関数は Color オブジェクトを参照渡して受け取りますが、中身を書き換えていないため、const 引数として宣言しています。
const ポインタ
ポインタ変数の宣言に const をつけることで、ポインタの指し示す内容を書き換えることができなくなります。
Bool IsBlack(const Color * color) { return (color->r == 0 && color->g == 0 && color->b == 0); }
const メンバ関数
メンバ関数の宣言の末尾に const 修飾子をつけることで、そのメンバ関数を呼び出したときにオブジェクトが変化しないことを宣言できます。このように宣言することで、const オブジェクトに対してもメソッド呼び出しを行うことができます。const オブジェクトに対して呼び出せるメソッドは、const メンバ関数だけです。
たとえば、次のようなコードを考えてみましょう。
class Color { private: UInt08 r, g, b; public: Color() {} Color(UInt08 r0, UInt08 g0, UInt08 b0) { r = r0; g = g0; b = b0; } UInt08 GetRed() const { return r; } UInt08 GetGreen() const { return g; } UInt08 GetBlue() const { return b; } Void SetRed(UInt08 n) { r = n; } Void SetGreen(UInt08 n) { g = n; } Void SetBlue(UInt08 n) { b = n; } }; Color MakeComplemetaryColor(const Color& color) { Color c; c.SetRed(255 - color.GetRed()); c.SetGreen(255 - color.GetGreen()); c.SetBlue(255 - color.GetBlue()); return c; }
MakeComplemetaryColor() 関数は、Color の const オブジェクトを引数にとりますが、そのオブジェクトに対して呼び出せるメソッドは const メンバ関数である GetRed(), GetGreen(), GetBlue()だけです。
SetRed(), SetGreen(), SetBlue() などの関数に対してもconst 修飾子をつけることで、const オブジェクトに対してどんなメソッドでも呼び出せるようにできますが、これらのメソッドは実質的にオブジェクトの状態を変更しているので、推奨されません。実際、そのような宣言を行うと、結果は予測されないものになります。
const 修飾子を指定する意味
const 修飾子を指定することで、コンパイラは最適化をしやすくなります。
また、変数の使用方法に制限をつけることで、誤ったプログラミングを未然に防ぐことができます。
この章のまとめ
- 変数宣言に const 修飾子を指定すると、その変数の値を書き換えることができなくなります。
- ポインタ変数の宣言に const 修飾子を指定することで、そのポインタの中身を書き換えることができなくなります。
- const オブジェクトに対して呼び出せるメソッドは、 const メンバ関数だけです。
やってみよう
次のようなコードを実行してみよう! Rectangle::GetWidth() メソッドの const をはずすとどうなるでしょうか? どのようなエラーになるでしょうか?
class Rectangle { private: SIntN x, y, w, h; public: Rectangle(SIntN x0, SIntN y0, SIntN w0, SIntN h0) { x = x0; y = y0; w = w0; h = h0; } SIntN GetWidth() const { return w; } SIntN GetHeight() const { return h; } Void SetWidth(SIntN w0) { w = w0; } Void SetHeight(SIntN h0) { h = h0; } }; Bool IsSquare(const Rectangle& rect) { // rect.SetWidth(100); // コンパイル エラー return (rect.GetWidth() == rect.GetHeight()); } Void TestConst(Void) { const SIntN WIDTH = 4; // WIDTH = 5; // コンパイル エラー Rectangle rect(10, 15, WIDTH, WIDTH); if (IsSquare(rect)) SFXHelper::dbgprintf("rect is square."); else SFXHelper::dbgprintf("rect is not square."); }