構造体の埋め込み
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 28/61。
C++やJavaのようなオブジェクト指向言語では、継承によってクラスはparentクラスからプロパティを取得できます。Cには組み込みの継承はありませんが、1つのstructを別のstructの中に配置する、コンポジションと呼ばれる手法を使ってこれをシミュレートできます。
考え方は単純です。Child が Parent のすべてのプロパティを必要とする場合、Parent 構造体を Child のメンバーとして埋め込みます。
typedef struct {
int id;
char name[50];
} Parent;
typedef struct {
Parent parent; // 埋め込み構造体
int grade;
} Child;ここでは、ChildにはParentが持つすべてのものに加えて、独自のgradeフィールドが含まれています。これはコンポジションです。子は親「である」のではなく、親「を持つ」ことになりますが、その効果は継承と似ています。
子インスタンスを通じて親のメンバーにアクセスするには、ドット演算子を2回使用します:
Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;このパターンは、Cで型階層を構築するための基盤となります。base struct をfirst memberとして埋め込むことで、今後のレッスンで詳しく学ぶ強力なテクニックを活用できるようになります。
チャレンジ
簡単Cにおける継承の基礎である構造体の埋め込みを示す、シンプルな employee 管理システムを作成しましょう。
Employee が Person を含む階層構造を作成します。これは継承の仕組みを反映しています。つまり、employee "is a" person であり、さらに職務に関する information を持つということです。Person 構造体を Employee の内部に埋め込むことで、person のすべてのプロパティに加えて、employee 固有のフィールドも利用できます。
コードを3つのファイルに整理します。
types.h:ここで include ガードとともに両方の構造体を Define します。まず、2つのフィールドを持つPerson構造体を作成します。フィールドはname(50 characters の character array)とage(integer)です。次に、Personを first member として埋め込み、employee_idフィールド(integer)を追加したEmployee構造体を define します。types.c:Employeeへの pointer を受け取り、その information を表示するprint_employeeという Function を Implement します。学習した chained dot/arrow 構文を使用して、埋め込まれた person の data に access します。main.c:Employeevariable を作成し、埋め込まれた person の name と age を含むすべてのフィールドを Populate して、print Function を使用して information を表示します。
3つの入力を受け取ります。employee の name(string)、age(integer)、および employee ID(integer)です。
print_employee Function は、employee の information を次の形式で出力します。
Employee: Alice
Age: 28
ID: 1001ここで、Alice は name、28 は age、1001 は入力された employee ID です。
埋め込まれた構造体の member には parent member を通して access することを忘れないでください。たとえば、name に到達するには、まず person member を経由します。
自分で試してみよう
#include <stdio.h>
#include <string.h>
#include "types.h"
int main() {
// 入力を読み取る
char name[50];
int age;
int employee_id;
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = '\0'; // 改行を削除
scanf("%d", &age);
scanf("%d", &employee_id);
// TODO: Employee変数を作成する
// TODO: 埋め込まれたpersonのnameとageを設定する
// Hint: 名前にはstrcpyを使い、employee.person.nameでアクセスする
// TODO: employee_idを設定する
// TODO: employeeへのポインタでprint_employeeを呼び出す
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ