C言語でクラス表現

# やろうとしていること。

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

# 背景

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

# 方針

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


# コード(ヘッダのみ)

## 親クラス
```Controller.h
#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
```

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

```Common.h
// 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 )
```


## 継承クラス(子クラス)
```PanelController.h
#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
```

## 使用例

```main.c
// 実体化
struct PanelController controller = PanelController_Init;

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

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

# 参考
- [C言語でオブジェクト指向を表現する (クラス、継承) - Qiita](https://qiita.com/qiita_kuru/items/8f3441bce9b2f53d1d62)
   - コンストラクタ
   - メソッド継承はなし
- [C 言語によるオブジェクト記述法 COOL](http://www.sage-p.com/process/cool.htm)
   - メソッドの継承も含む
   - ちょっと複雑
- [SMC: The State Machine Compiler](http://smc.sourceforge.net/)
   - StateMachineのコード生成にはSMCを使うので、SMCの吐き出すC言語コードも参考にする。