オブジェクトとしての構造体
CoddyのCジャーニー「Object Oriented Programming」セクションの一部 — レッスン 6/61。
オブジェクト指向言語では、オブジェクトとは、データ(状態)と、そのデータを操作する関数(メソッド)をまとめた実体です。C言語には組み込みのオブジェクトはありませんが、構造体(structs)と関数(functions)を使用することで、同じ概念を実現できます。
構造体(struct)をオブジェクトの「データ」部分と考えてください。それは状態、つまりオブジェクトが現在何であるかを定義する値を保持します:
typedef struct {
int value;
} Counter;
この Counter 構造体は、単一の状態(現在の値)を持つエンティティを表します。これに振る舞いを与えるために、この構造体をパラメータとして受け取る関数を記述します:
void counter_increment(Counter *c) {
c->value++;
}
int counter_get(Counter *c) {
return c->value;
}
これらの関数はメソッドのように動作します。これらは特にCounterデータに対して操作を行います。構造体を関数に渡すことで、counter.increment()を呼び出したときに他の言語が自動的に行うことをシミュレートしています。
int main() {
Counter my_counter = {0};
counter_increment(&my_counter);
printf("%d\n", counter_get(&my_counter)); // 出力: 1
return 0;
}
命名規則 typename_action(counter_increment など)は、コードを整理し、関数がどの構造体に属しているかを明確にするのに役立ちます。このパターンは、C言語におけるオブジェクト指向プログラミングの基礎となります。
チャレンジ
簡単構造体を振る舞いを持つオブジェクトとして扱う、シンプルな Counter モジュールを作成しましょう。データとそれを操作する関数をバンドルするパターンを練習するために、コードを3つのファイルに整理します。
以下の3つのファイルを作成します:
counter.h: 1つのint valueメンバを持つCounter構造体を宣言するヘッダーファイルです。また、カウンターの「メソッド」として機能する2つの関数、counter_increment(Counter へのポインタを受け取り、その値を1増やします)とcounter_get(Counter へのポインタを受け取り、その現在の値を返します)も宣言してください。インクルードガードにはCOUNTER_Hというシンボルを使用してください。counter.c: 両方の関数を実装するソースファイルです。ヘッダーファイルをインクルードすることを忘れないでください。main.c: Counter を作成し、それに対して操作を行い、結果を表示するメインファイルです。
2つの整数入力を受け取ります。カウンターの開始値と、それをインクリメントする回数です。
メインファイルで、開始値を使用して Counter を初期化し、指定された回数だけ counter_increment を呼び出します。最後に、counter_get を使用して最終的な値を取得し、表示します。
結果を次の形式で出力してください:
Final value: {result}例えば、開始値が 5 でインクリメントが 3 回の場合、出力は次のようになります:
Final value: 8チートシート
C言語では、構造体(データ)と、それらの構造体を操作する関数(振る舞い)を組み合わせることで、オブジェクト指向プログラミングをシミュレートできます。
状態を保持するための構造体を定義します:
typedef struct {
int value;
} Counter;
構造体をパラメータとして受け取ることで、「メソッド」として機能する関数を作成します:
void counter_increment(Counter *c) {
c->value++;
}
int counter_get(Counter *c) {
return c->value;
}
構造体と関数を組み合わせて使用します:
Counter my_counter = {0};
counter_increment(&my_counter);
printf("%d\n", counter_get(&my_counter)); // 出力: 1
typename_action(例:counter_increment)という命名規則は、コードを整理し、関数がどの構造体を操作するのかを明確にするのに役立ちます。
自分で試してみよう
#include <stdio.h>
#include "counter.h"
int main() {
// 入力を読み込む
int starting_value;
int num_increments;
scanf("%d", &starting_value);
scanf("%d", &num_increments);
// TODO: Counterを作成し、starting_valueで初期化する
// TODO: 指定された回数だけcounter_incrementを呼び出す
// TODO: counter_getを使用して最終的な値を取得し、表示する
// 出力形式: "Final value: {result}"
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。