C言語でクラス表現

クラス図 C言語

やろうとしていること。

  • C言語でクラスを表現したい。

背景

  • C言語のコンパイラしかない組み込み系などでは、UMLでクラス図書いても何かむなしい。
  • よってC言語でもクラスっぽい表現で記述したい。

方針

  • クラスはstructで表現。
  • メンバはstructのメンバそのもの。
  • 継承を実現するため、メソッドは関数ポインタをstructのメンバにして、初期化時にメソッド実体のポインタを渡す。
  • クラス(struct)の初期化はマクロを用意する。
  • メソッドの呼び出しも親側で呼び出しマクロを用意する。初期化時に与えられた関数ポインタにより、親子どちらかの適切な方のメソッド実体が呼び出される。
  • privateメンバ、メソッドは.cファイル側にstaticにして記述し隠す。
  • protectedはあきらめてpublicにする(ヘッダに書く)。

コード(ヘッダのみ)

親クラス

#ifndef _CONTROLLER_H_INCLUDED_
#define _CONTROLLER_H_INCLUDED_

#include "Common.h"

// クラス定義
struct Controller {
    // メンバ: _で名称開始
    int _data;

    // メソッド
    // 関数ポインタで表現
    void ( *Initialize )( struct Controller* const self );
    void ( *Execute )( struct Controller* const self );
};

/// コンストラクタ
extern void Controller_Constructor(
    struct Controller* const self,
    int data );

// メソッド実体定義
extern void Controller_Initialize( struct Controller* const self );
extern void Controller_Execute( struct Controller* const self );

/// メンバー初期化定義
#define Controller_InitMembers \
    ._data = 0,                                 

/// メソッド初期化定義
#define Controller_InitMethods \
    .Initialize = Controller_Initialize,   \
    .Execute = Controller_Execute,   \

/// 初期化定義
#define Controller_Init                \
    {                                          \
            Controller_InitMembers     \
                Controller_InitMethods \
    }

// 仮想メソッドの呼び出し
#define Controller_initialize( self ) V_METHOD( self, Controller, Initialize )
#define Controller_execute( self ) V_METHOD( self, Controller, Execute)

#define _Controller( self ) ( (struct Controller*)self )
#endif

共通ヘッダ

共通ヘッダでの仮想メソッド呼び出しマクロを定義

// Virtual Method General
#define V_METHOD( self, Type, Method ) ( (struct Type*)( self ) )->Method( (struct Type*)( self ) )
#define V_METHOD_ARG1( self, Type, Method, arg1 ) ( (struct Type*)( self ) )->Method( (struct Type*)( self ), arg1 )
#define V_METHOD_ARG2( self, Type, Method, arg1, arg2 ) ( (struct Type*)( self ) )->Method( (struct Type*)( self ), arg1, arg2 )

継承クラス(子クラス)

#ifndef _PANEL_CONTROLLER_H_INCLUDED_
#define _PANEL_CONTROLLER_H_INCLUDED_

#include "Controller.h"

// 子クラス定義
struct PanelController {
    // 親クラスを実体として持つ
    struct Controller __baseClass;

    // 子クラスのメンバ
    int _height;

    // 子クラスのメソッド
    int ( *GetHeight )( struct PanelController* const self );
};

// メンバ定義
extern void PanelController_Initialize( struct Controller* const self );
extern void PanelController_Execute( struct Controller* const self );
extern int PanelController_GetHeight( struct Controller* const self );

/// コンストラクタ
extern void PanelController_Constructor(
    struct PanelController* const self,
    int data,
    int height );


/// 親クラス初期化定義
#define PanelController_InitParent        \
    {                                              \
        Controller_InitMembers                 \
        .Initialize = PanelController_Initialize,                \
        .Execute = PanelController_Execute,                \
    },

/// メンバー初期化定義
#define PanelController_InitMembers \
   ._height = 0, 

/// メソッド初期化定義
#define PanelController_InitMethods \
   .GetHeight = PanelController_GetHeight, 

/// 初期化定義
#define PanelController_Init                \
    {                                                \
        PanelController_InitParent          \
            PanelController_InitMembers     \
                PanelController_InitMethods \
    }

#define _PanelController( self ) ( (struct PanelController*)self )
#endif

使用例

// 実体化
struct PanelController controller = PanelController_Init;

// コンストラクタ
PanelController_Constructor( &controller, 100, 200 );

// メソッド呼び出し
Controller_initialize( &controller );
Controller_execute( &controller );

参考

Qiitaにも同様の記事を載せています。

C言語でクラス表現 - Qiita
# やろうとしていること。 - C言語でクラスを表現したい。 # 背景 - C言語のコンパイラしかない組み込み系などでは、UMLでクラス図書いても何かむなしい。 - よってC言語でもクラスっぽい表現で記述したい。 # 方針 ...

コメント

タイトルとURLをコピーしました