ここで、僕のC99でのProtectedの実装を披露いたします。考えとしては、Protected部分を別の.h/.cファイルにすることである。
// ifcs_ooc_class_a_protected.hファイル
#ifndef IFCS_OOC_CLASS_A_PROTECTED_H
#define IFCS_OOC_CLASS_A_PROTECTED_H
#if defined (__cplusplus)
extern "C" {
#endif
// Protected部分の構造体
typedef struct IfcsClassAProtected_tag {
float f;
void print_float_value(struct IfcsClassAProtected_tag* const);
} IfcsClassAProtected;
// Protected部分の生成
extern
IfcsClassAProtected*
IfcsClassAProtected_create();
// Protected部分の消滅
extern
void
IfcsClassAProtected_destroy(
IfcsClassAProtected* const self);
#if defined (__cplusplus)
}
#endif
#endif /* IFCS_OOC_CLASS_A_PROTECTED_H */
------------- 分割線 ----------------
// ifcs_ooc_class_a_protected.cファイル
#include <stdio.h>
#include "ifcs_ooc_class_a_protected.h"
// 関数の実装
static
void
print(IfcsClassAProtected* const self)
{
printf("Print From Protected, value=%f\n", self->f);
}
// 外部関数の実装
IfcsClassAProtected*
IfcsClassAProtected_create()
{
IfcsClassAProtected* p_protected = NULL;
if (NULL == (p_protected = (IfcsClassAProtected*)malloc(sizeof(IfcsClassAProtected)))) {
return NULL;
}
p_protected->print_float_value = print;
}
void
IfcsClassAProtected_destroy(
IfcsClassAProtected* const self)
{
memset(self, 0x00, sizeof(IfcsClassAProtected));
free(self);
}
以上はProtected部分の実装の例。続いては、Protected部分をClassに取り入れる。下の void *p_protected部分を注目しましょう。
// ifcs_ooc_class_a.h ClassAの定義、void *p_privateでprivateの部分を隠す
typedef struct IfcsClassA_tag {
// public:
int input_val;
void printVal(struct IfcsClassA_tag* const);
/* Protected部分の機能をInvokeする */
void printFloatVal(struct IfcsClassA_tag* const);
// private:
void *p_private;
/* protected: */
void *p_protected;
} IfcsClassA;
------------- 分割線 ----------------
// ifcs_ooc_class_a.c の実装、なかでprivateの部分を定義する
#include "ifcs_ooc_class_a.h"
/* Protected部分を別のファイルにして、.cファイルからincludeする */
#include "ifcs_ooc_class_a_protected.h"
// <1>. Privateの内容を1つのStruct構造体で格納して、実装を書く
typedef struct IfcsClassAPrivate_tag {
int count;
void calc_value(struct IfcsClassAPrivate_tag* const, int const);
} IfcsClassAPrivate;
static int calc_value(IfcsClassAPrivate* const p_private, int const origin) {
if (NULL != p_private) {
int result = p_private->count + origin;
p_private->count++;
return result;
} else {
return origin;
}
}
static IfcsClassAPrivate* IfcsClassAPrivate_create() {
IfcsClassAPrivate *p_private = NULL;
p_private = (IfcsClassAPrivate*)malloc(sizeof(IfcsClassAPrivate));
p_private->calc_value = calc_value;
p_private->count = 0;
...
return p_private;
...
}
...
// Privateの部分はここまで
// ここからは、ClassAのpublicの部分の内容です。
static void printVal(IfcsClassA * const self);
static void printFloatVal(IfcsClassA * const self);
IfcsClassA*
IfcsClassA_create() {
/* Protected部分のPointer */
IfcsClassAProtected* p_protected = NULL;
...
p_obj_a->p_private = IfcsClassAPrivate_create();
...
p_obj_a->printVal = printVal;
...
/* Protected部分の生成 */
p_protected = IfcsClassAProtected_create();
p_protected->f = 0.1;
p_obj_a->p_protected = p_protected;
p_obj_a->printFloatVal = printFloatVal;
}
void
IfcsClassA_destroy(
IfcsClassA ** const self) {
/* Protected部分のPointer */
IfcsClassAProtected* p_protected = ()p_obj_a->p_protected;
...
IfcsClassAPrivate_destroy(&p_obj_a->p_private);
...
/* Protected部分の消滅 */
IfcsClassAProtected_destroy(p_obj_a->p_protected);
p_obj_a->p_protected = NULL;
}
static void IfcsClassA_initialize(IfcsClassA * const self) {
...
self->input_val = 0;
...
}
static void printVal(
IfcsClassA * const self)
{
IfcsClassAPrivate *p_private = NULL;
int result = -1;
if (NULL != self) {
result = self->input_val;
if (NULL != self->p_private) {
// Cのポインター変換で、private領域を内部でアクセスする
p_private = (IfcsClassAPrivate*)self->p_private;
result = p_private->calc_value(p_private, result);
}
}
printf("class a value is %d\n", result);
}
/* Protected関数をInvokeする */
static void printFloatVal(
IfcsClassA * const self)
{
IfcsClassAProtected *p_protected = NULL;
assert((NULL != self) && (NULL != self->p_protected));
p_protected = (IfcsClassAProtected*)self->p_protected;
p_protected->print_float_value(p_protected);
}
これでProtected部分をClassに取り入れました。次にそれを使ってみよう。
int main(int argc, char *argv[]) {
int i = 0;
IfcsClassA *p_obj_a = IfcsClassA_create();
p_obj_a->input_val = 1;
for (; i < 10; ++i) {
p_obj_a->printVal(p_obj_a);
}
/* Protected部分を使う */
p_obj_a->printFloatVal(p_obj_a);
p_obj_a->finalize(p_obj_a);
IfcsClassA_destroy(&p_obj_a);
}
以上です。
まとめ:C言語のポインタの変換機能をうまく利用して、クラス内にPrivate部分と同じくvoid*のポインタを用意する。次に、Private部分を直接にクラスの.cの内部に書くのと違って、別のファイルとしてProtected部分を書き出すこと。すると、クラスを通してProtected部分を直接にアクセスできないが、また別のクラスを作る場合、Protected部分をファイルのIncludeで流用することができる。