2023年11月14日火曜日

cppのクラスメンバ関数のconst備忘録


背景

cppのプログラムでconstを付けてエラーが出る度にどうだったか迷うので、自分の言葉でまとめます。

クラスメンバ関数のconst

下記のプログラムを書いた時
class Item {
public:
float getValue() const { return value; }
void setValue(float v) { this->v = v; }

private:
float value = 5;
};

class A {
public:
const Item* const getItemP(size_t index) const { return &items[index]; }

private:
static const size_t lenItems = 10;
Item items[lenItems];
};

下記でどれが欲しい機能のconstだったか戸惑います
class A {
const Item* const getItemP(size_t index) const { return &items[index]; }
};

戻り値の前のconst: 変更を許可しない戻り値(この場合ポインタ)を返す

こう書いていると
class A {
const Item* getItemP(size_t index) { return &items[index]; }
^^^^^
};
getItemPで受け取るポインタが変更を許可しないconst扱いになります。
A a;
auto itemP = a.getItemP(0);
itemP->setValue(5); // Error

戻り値と関数名の間のconst: 処理内容が変わらない関数?現時点で意味不明

役割不明です。
ご存知の方はコメントなどで教えていただけると嬉しいです。
class A {
Item* const getItemP(size_t index) { return &items[index]; }
^^^^^ 何が嬉しいかが分からない
};

引数の丸括弧終わりと関数の処理の間のconst: 関数の処理でメンバ変数の変更を許可しない

こう書いていると
class A {
Item* getItemP(size_t index) const { return &items[index]; }
^^^^^
};
this(インスタンス)がconst扱いになり関数の中でメンバ変数の変更を許可しません。
変更する記述があるとエラーになります。(ただし、mutable付きで宣言しているメンバ変数だと変更できてしまうようです。参考: const メンバ変数内であっても変数が書き換えられてしまう場合がある

この記述の嬉しい(というかこれが無いとエラーが出て使えない)場面は、クラスのインスタンスをconst型として扱う場合に、値を参照するだけのconstのインスタンスから関数として呼べることです。
void someFunction (const A& a) {
auto itemP = a.getItemP(5); // 処理の前のconstが無いとエラーになる
}

おわり

クラスメンバ変数に3箇所も書けるconstの役割の理解が深まりました。
真ん中のconstだけ嬉しい場面が分からないので、どなたか教えていただけると嬉しいです。

参考

c++ constメンバ関数まとめ
メンバ関数の左辺値/右辺値修飾

0 件のコメント :