2010年5月1日土曜日

C++でenumにtoStringを実装してみる

今日は、C++でenumtoString()を実装してみたいと思います。
え!?、出来るのかって?クラスでカプセル化するだけですがなにか・・・?
ってことでクラス図です。
状態(State)を管理するenumを適当に宣言してクラスのメンバ変数としてます。
んでもってtoString()メソッドを宣言してあります。
 つぎにソースを見てみましょう、用意するのは次のファイルです。
  • main.cpp
  • EState.h
  • EState.cpp
まずはEState.hです。
#ifndef _E_STATE_H_
#define _E_STATE_H_

enum State {    //  ①
    WAIT_INIT = 0,
    IDLE,
    PLAY,
    PAUSE,
};

class EState {
    //----------------------------------
    //  フィールド
    //----------------------------------
private:
    State m_state;  //  状態

    //----------------------------------
    //  プロパティ
    //----------------------------------
private:    //  ②
    //  状態取得
    const State getState() const ;
    //  状態設定
    EState& setState(const State _state);

    //----------------------------------
    //  メソッド
    //----------------------------------
public:
    //  コンストラクタ
    EState();
    EState(const EState& _state);   //  ③
    EState(const State _state);

    //  デストラクタ
    ~EState();

    //  operator
    operator State() const; //  ④
    EState& operator=(const EState& _state);    //  ⑤

    //  toString
    const char* toString() const;   //  ⑥
};
#endif 
①enumを宣言しています。
②状態のgetter、setterですがインタフェースを減らすためにprivateにしてあります。
③コピーコンストラクタです。
④キャストoperatorです。これによりEStateからStateへの代入を可能にしています。後ろにconstが着いているのはconst化された変数からも呼び出せるようにです。
⑤代入operatorです。
⑥toString()メソッドです。

つぎに、EState.cppです。
#include "EState.h"

//----------------------------------
//  プロパティ
//----------------------------------
//  状態取得
const State EState::getState() const
{
    return this->m_state;
}
//  状態設定
EState& EState::setState(const State _state)
{
    this->m_state = _state;
    return *this;
}

//----------------------------------
//  メソッド
//----------------------------------
//  コンストラクタ
EState::EState() :
    m_state(WAIT_INIT)  //  ①
{
    // do nothing...
}
EState::EState(const EState& _state) :
    m_state(WAIT_INIT)  //  ①
{
    *this = _state;
}
EState::EState(const State _state) :
    m_state(WAIT_INIT)  //  ①
{
    this->m_state = _state;
}

//  デストラクタ
EState::~EState()
{
    //  do nothing...
}

//  operator
EState::operator State() const
{
    return this->m_state;
}
EState& EState::operator=(const EState& _state)
{
    this->m_state = _state.m_state;
    return *this;
}

//  toString
const char* EState::toString() const
{
    static const char* strArray[] = {
        "WAIT_INIT",
        "IDLE",
        "PLAY",
        "PAUSE",
    };

    return strArray[this->getState()];  //  ②
} 
初期化指定子で初期状態を設定しています。
②対応する文字列を返却しています。なにげないコードですがデータとロジックを分けることによってバグが少なくメンテナンスが容易になっています。

最後にmain.cppです。
#include 
#include "EState.h"

void main(void)
{
    const EState state; //  ①
    printf("state:%s\n", state.toString());   //  ②
    const State tempState = state;  //  ③

    printf("hit any key...");
    while(getchar() == EOF){}
}
①実装したEStateクラスを使用してstateを定義しています。
②toString()メソッドを呼び出して出力しています。
③キャストoperatorを実装しているのでEState型からState型への代入も可能です。

以上ですが、たかがtoString()の為だけにこれだけのコードを書かないと行けないC++ってやっぱり生産性が低いのかな・・・?

0 件のコメント:

コメントを投稿