i-focus i-focus BB
    • カテゴリ
    • 最近
    • タグ
    • 人気
    • ユーザー
    • グループ
    • 登録
    • ログイン

    実開発に使われるC言語 [基礎から裏技まで] (5) Object-Oriented C その3 Protectedの実現

    C言語
    1
    1
    236
    もっと見る
    • 古いものから新しい順
    • 新しいものから古い順
    • 最高評価
    返信
    • スレッドとして返信する
    投稿するのにログインして下さい
    このスレッドが削除されました。スレッド管理権を持っているユーザーにしか読めません。
    • Z
      zhengyu.chen
      最後に編集した時間zhengyu.chen

      ここで、僕の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で流用することができる。

      1 件の返信 最後の返信 返信 引用 0
      • First post
        Last post