概要
マルチインスタンスモジュールとは
アプリケーションによっては、同じモジュールに異なるデータと状態を持たせるために、複数のインスタンスが必要になるだろう。たとえば、複数のFIFO データを必要とするアプリケーションが考えられる。
(テスト駆動開発による組み込みプログラミング)
C++ や java や python 等ではクラスを書いてインスタンス生成すれば、別々の状態をもったオブジェクトを管理できますが、C にはクラスがないので工夫が必要となります。
つくるもの
カウンターをつくります。機能は以下の通りです。
- カウントアップ
- カウントダウン
- カウントを出力
- カウントをリセット
構造体を定義する
内部データを格納するための構造体を定義します。
// counter.c
#include "counter.h"
typedef struct CounterStruct
{
int count;
int subtotalCount;
} CounterStruct;
構造体はヘッダファイルでポインタ型として typedef しておきます。
// counter.h
typedef struct CounterStruct *Counter;
これにより構造体の中身を隠蔽したまま、外部(counter.hをインクルードしたコード)から利用できるようになりました。
コンストラクタとデストラクタ
インスタンスを生成(メモリを確保)するコンストラクタと、破棄(メモリを開放)するデストラクタを書きます。
// counter.c
Counter Counter_Create(void)
{
Counter self = malloc(sizeof(CounterStruct));
self->count = 0;
self->subtotalCount = 0;
return self;
}
void Counter_Destroy(Counter self)
{
free(self);
}
どのようにして使うかというと、
#include counter.h
int main(void){
Counter myCounter1;
Counter myCounter2;
// まずポインタを宣言。このときまだメモリは確保されていない
myCounter1 = Counter_Create();
myCounter2 = Counter_Create();
// Counter_Create() 内でメモリが確保され、そのアドレスが返り値で渡される
// 返り値をさっきつくった myCounter ポインタにセットする
Counter_Destroy(myCounter1);
Counter_Destroy(myCounter2);
// 使い終わったらメモリを開放する
}
機能をつくる
関数は第一引数として Counter 型をとります。たとえばカウントをインクリメントする関数は
void Counter_CountUp(Counter self)
{
self->count++;
}
となります。
変数の値を取得する
Counter 型の詳細は隠蔽されているので、変数にアクセスするためには関数を通して値を取得します。
int Counter_GetCount(Counter self)
{
return self->count;
}
まとめ
- ひとつのコードで複数の状態をもてる
- 構造体の詳細は隠蔽する
- 変数に直接アクセスさせない
- 今回のコード:https://github.com/paragraph14/qiita-code/tree/master/counter