コンストラクタパターン
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 12/61。
Java や C++ のような言語では、コンストラクタを使ってオブジェクトを作成します。コンストラクタは、メモリを自動的に確保してフィールドを初期化する特殊な関数です。C にはそのような機能はありませんが、単純なパターン、つまり create_ 関数を使ってシミュレートできます。
Cにおけるコンストラクター関数は、通常、次の3つの処理を行います。mallocを使ってメモリを割り当て、すべてのフィールドを適切な値で初期化し、新しいオブジェクトへのポインターを返します。
typedef struct {
char *name;
int age;
} Person;
Person *create_person(const char *name, int age) {
Person *p = malloc(sizeof(Person));
p->name = malloc(strlen(name) + 1);
strcpy(p->name, name);
p->age = age;
return p;
}
function は pointer を返します。これは、オブジェクトがスタックではなくヒープ上に存在するためです。そのため、function が return した後も存続し、自由に受け渡すことができます。呼び出し元では次のように使用します。
Person *alice = create_person("Alice", 30);
printf("%s is %d years old\n", alice->name, alice->age);
コンストラクターが、構造体の割り当て、文字列用の領域の割り当て、データのコピーといった面倒な細部をすべて処理していることに注目してください。呼び出し元は初期値を指定するだけで、すぐに使えるオブジェクトを受け取れます。これにより、作成ロジックを1か所にカプセル化でき、コードがより簡潔で、エラーも起こりにくくなります。
チャレンジ
簡単ヒープ上に本のオブジェクトを作成する、コンストラクタパターンを使用した Book モジュールを構築しましょう。すべてのメモリ割り当てと初期化を処理し、すぐに使用できるポインタを返す create_ function の記述を練習します。
3つのファイルを作成します。
book.h: 2つのメンバーを持つBook構造体を Declare します。メンバーは、(dynamically allocated された文字列への pointer である)char *titleとint pagesです。また、title 文字列と page 数を受け取り、新しく作成された Book へのポインタを返すコンストラクタ functioncreate_bookも Declare します。シンボルBOOK_Hを使用して include guards を実装します。book.c:create_bookfunction を Implement します。コンストラクタでは、まず Book 構造体自体のために memory を Allocate し、次に title 文字列用に別の memory を Allocate します(null terminator 分を確保することを remember してください)。title を新しい memory に Copy し、pages field を設定して、新しい Book への pointer を return します。main.c: コンストラクタを使用して book を作成し、その information を表示します。
2つの入力を受け取ります。book title(文字列)とnumber of pages(整数)です。
main ファイルでは、create_book を使用して provided の値で新しい book を作成し、次の format でその information を Print します。
Title: {title}
Pages: {pages}たとえば、入力が The C Programming Language と 272 の場合、出力は次のようになります。
Title: The C Programming Language
Pages: 272コンストラクタがすべての作成ロジックをカプセル化していることを remember してください。呼び出し側は初期値を provided するだけで、すぐに使用できる fully initialized object を受け取ります。
自分で試してみよう
#include <stdio.h>
#include <stdlib.h>
#include "book.h"
int main() {
char title[256];
int pages;
// 入力を読み取る
fgets(title, sizeof(title), stdin);
// 改行があれば削除する
for (int i = 0; title[i]; i++) {
if (title[i] == '\n') {
title[i] = '\0';
break;
}
}
scanf("%d", &pages);
// TODO: create_book を使用して、指定された値で新しい本を作成する
// TODO: 必要な形式で本の情報を出力する:
// Title: {title}
// Pages: {pages}
// TODO: 完了したら割り当てられたメモリを解放することを忘れないでください
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ