constメンバー関数
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 29/104。
前のレッスンでは、getter メソッドに const キーワードが付いているのを見ました。しかし、const が関数のパラメーターリストの後に現れる場合、それは正確には何を意味するのでしょうか?const メンバー関数は、オブジェクトのメンバー変数を変更しないことを保証します。
class Rectangle {
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {}
int getArea() const { // const メンバ関数
return width * height; // メンバの読み取りは許可されています
}
void setWidth(int w) { // Non-const - オブジェクトを変更します
width = w;
}
};パラメータリストの後にある const は、コンパイラに「この関数はオブジェクトの状態を変更しない」と伝えます。const 関数内で member 変数を変更しようとすると、コンパイラはエラーを生成します。
これは const オブジェクトや const 参照を扱う際に不可欠になります。const オブジェクトは const メンバー関数のみを呼び出せます。
void printArea(const Rectangle& rect) {
std::cout << rect.getArea(); // OK - getArea() は const
// rect.setWidth(10); // ERROR - setWidth() は const ではない
}オブジェクトを変更しない const として function をマークするのは良い実践です。これは意図を文書化し、function が const オブジェクトで動作できるようにし、コンパイラーが意図しない変更を検出するのに役立ちます。データを読み取るだけの member function は、const としてマークする必要があります。
チャレンジ
簡単const メンバー関数をいつ、なぜ使用するのかを示す温度変換器を作成しましょう。一部のメソッドはデータを読み取るだけなので const にし、その他のメソッドはオブジェクトの状態を変更する class を作成します。
コードを整理するために、2つのファイルを作成します。
Temperature.h:温度の値を保持し、読み取りや変更を行うさまざまな方法を提供するTemperatureclass を define します。class には次の要素を含めます。- 温度を保持するための private member
celsius(double) - initial Celsius value を受け取る Constructor
- 保持されている値を返す
getCelsius()method。データを読み取るだけなので const にする必要があります celsius * 9.0 / 5.0 + 32.0という Formula を使用して温度を Fahrenheit で計算して返すgetFahrenheit()method。何も変更しないため、これも const にしますcelsius + 273.15を使用して温度を Kelvin で返すgetKelvin()method。これも const にします- 保持されている温度を更新する
setCelsius(double value)method。オブジェクトを変更するため、これは const にできません - 現在の温度に delta を加える
adjustBy(double delta)method。これも non-const です
- 温度を保持するための private member
main.cpp:通常のオブジェクトと const オブジェクトの両方で、const member functions がどのように動作するかを示します。input から initial temperature value を読み取り、次の処理を行います。- input value を使用して
Temperatureobject を Create します "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"を Print します- 温度を
10.0degrees Adjust します "After adjustment: <celsius>C"を Print します- const reference を受け取り、
"Reading: <celsius>C, <fahrenheit>F"を Print する helper functionvoid printReadings(const Temperature& temp)を Create します。この function は temp に対して const methods だけを Call できます - 温度 object を使って
printReadings()を Call します - 温度を
0.0(freezing point)に設定します "Freezing point: <celsius>C = <fahrenheit>F"を Print します
- input value を使用して
<iomanip> の std::fixed と std::setprecision(1) を使用して、すべての温度の値を小数点以下1桁で Format します。
ここでの key insight は、printReadings() が const reference を受け取るため、const としてマークされた methods だけを Call できるということです。これが、getter methods を適切に const としてマークすることが重要な理由です。これにより、オブジェクトを変更できないコンテキストでもそれらを使用できるようになります。
自分で試してみよう
#include <iostream>
#include <iomanip>
#include "Temperature.h"
using namespace std;
// TODO: Temperatureクラスのメソッドをここに実装する
// コンストラクタ
Temperature::Temperature(double initialCelsius) {
// TODO: celsiusを初期化する
}
// TODO: getCelsius()をconstとして実装する
// TODO: getFahrenheit()をconstとして実装する
// TODO: getKelvin()をconstとして実装する
// TODO: setCelsius(double value)を実装する
// TODO: adjustBy(double delta)を実装する
// TODO: const Temperature&を受け取るヘルパー関数printReadingsを作成する
// そして "Reading: <celsius>C, <fahrenheit>F" を出力する
// Note: この関数はtempに対してconstメソッドのみを呼び出せます!
int main() {
double initialTemp;
cin >> initialTemp;
// 出力フォーマットを設定する
cout << fixed << setprecision(1);
// TODO: 入力値でTemperatureオブジェクトを作成する
// TODO: "Initial: <celsius>C = <fahrenheit>F = <kelvin>K" を出力する
// TODO: 温度を10.0度調整する
// TODO: Print "After adjustment: <celsius>C"
// TODO: 温度オブジェクトでprintReadings()を呼び出す
// TODO: Set the temperature to 0.0 (freezing point)
// TODO: Print "Freezing point: <celsius>C = <fahrenheit>F"
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタパラメータ付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ徹底解説Rule of Three / Five / Zero復習 - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () の演算子オーバーロード型変換演算子復習 - Matrixクラス自分で練習してみよう: C++オンラインコンパイラ