Menu
Coddy logo textTech

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 としてマークする必要があります。

challenge icon

チャレンジ

簡単

const メンバー関数をいつ、なぜ使用するのかを示す温度変換器を作成しましょう。一部のメソッドはデータを読み取るだけなので const にし、その他のメソッドはオブジェクトの状態を変更する class を作成します。

コードを整理するために、2つのファイルを作成します。

  • Temperature.h:温度の値を保持し、読み取りや変更を行うさまざまな方法を提供する Temperature class を 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 です
  • main.cpp:通常のオブジェクトと const オブジェクトの両方で、const member functions がどのように動作するかを示します。input から initial temperature value を読み取り、次の処理を行います。
    • input value を使用して Temperature object を Create します
    • "Initial: <celsius>C = <fahrenheit>F = <kelvin>K" を Print します
    • 温度を 10.0 degrees Adjust します
    • "After adjustment: <celsius>C" を Print します
    • const reference を受け取り、"Reading: <celsius>C, <fahrenheit>F" を Print する helper function void printReadings(const Temperature& temp) を Create します。この function は temp に対して const methods だけを Call できます
    • 温度 object を使って printReadings() を Call します
    • 温度を 0.0(freezing point)に設定します
    • "Freezing point: <celsius>C = <fahrenheit>F" を Print します

<iomanip>std::fixedstd::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;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C++オンラインコンパイラ