Const の妥当性
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 8/61。
メソッドとして機能する関数を書くとき、オブジェクトを変更するもの(player_take_damageなど)もあれば、何も変更せずにデータを読み取るだけのものもあります。constキーワードを使うと、この区別をコンパイラーレベルで強制できます。
ポインタパラメータに const を付けることで、そのポインタが指すデータを function が変更しないことを保証します。誤って member を変更しようとすると、コンパイラはエラーを生成します。
typedef struct {
int x;
int y;
} Point;
// この関数はポイントを読み取ることしかできません
void point_print(const Point *self) {
printf("(%d, %d)\n", self->x, self->y);
// self->x = 10; // ERROR: constポインタを通しては変更できません
}
// この関数はポイントを変更できます
void point_move(Point *self, int dx, int dy) {
self->x += dx;
self->y += dy;
}
const Point *self パラメータは、point_print が「getter」、つまり読み取り専用の操作であることを、コンパイラと他のプログラマーの両方に伝えます。これはconst correctnessと呼ばれ、変更が必要ない箇所ではどこでもconstを使用することを意味します。
この練習はバグを早期に発見します。display 関数を書いていて誤ってフィールドを変更すると、コンパイラーはバグがプログラムに入り込むのを許すのではなく、すぐに停止します。
チャレンジ
簡単Temperature モジュールを作成しましょう。このモジュールは温度の値を保持し、読み取り専用と変更操作の両方を提供します。これにより、データを単に読み取る関数とデータを変更する関数を明確に区別するための const ポインターの使い方を練習できます。
3つのファイルを作成します。
temperature.h:単一のdouble celsiusmember を持つTemperature構造体を Declare します。また、3つの関数も Declare します。temp_display:Temperature へのconstポインターを受け取り、Current 温度を出力します(読み取り専用)temp_adjust:Temperature への通常のポインターと double の amount を受け取り、amount を celsius に加えます(変更)temp_to_fahrenheit:Temperature へのconstポインターを受け取り、Fahrenheit に conversion した値を返します(読み取り専用)
TEMPERATURE_Hシンボルで include guards を使用します。temperature.c:3つの関数すべてを Implement します。temp_display関数はCurrent: {celsius}Cの Format で出力します。temp_to_fahrenheit関数はcelsius * 9.0 / 5.0 + 32.0を返します。constポインターを使用する関数は、構造体の data を MODIFY できないことに注意してください。main.c:Temperature を Create し、操作を実行して、結果を表示します。
2つの入力を受け取ります。1つ目はinitial celsius value(double として)、2つ目はadjustment amount(double として)です。
main ファイルでは、次の操作を行います。
- initial celsius value で
Temperatureを initialize します temp_displayを Call して開始時の温度を表示しますtemp_adjustを Call して adjustment amount によって温度を MODIFY しますtemp_displayを again Call して更新後の温度を表示しますtemp_to_fahrenheitを使用して Fahrenheit conversion を Print します
結果を次の Format で Print します。
Current: {celsius}C
Current: {celsius}C
Fahrenheit: {fahrenheit}Fすべての温度の値には %.1f を使用し、小数点以下1桁で表示します。
たとえば、initial value が 20.0、adjustment が 5.0 の場合、出力は次のようになります。
Current: 20.0C
Current: 25.0C
Fahrenheit: 77.0F自分で試してみよう
#include <stdio.h>
#include "temperature.h"
int main() {
double initial_celsius, adjustment;
scanf("%lf", &initial_celsius);
scanf("%lf", &adjustment);
// TODO: Temperature構造体を作成し、initial_celsiusで初期化する
// TODO: temp_displayを呼び出して開始温度を表示する
// TODO: temp_adjustを呼び出してadjustmentの量だけ温度を変更する
// TODO: temp_displayを再度呼び出して更新された温度を表示する
// TODO: temp_to_fahrenheitを使用して華氏変換を出力する
// 形式: "Fahrenheit: %.1fF\n"
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ