CArray クラステンプレート
Array.h
// Array.h
#ifndef __ARRAY_H__INCLUDED__
#define __ARRAY_H__INCLUDED__

#include <iostream.h>
#include <stdlib.h>

template <typename TYPE>
class CArray
{
    // メンバ変数
private:
    TYPE* m_pnum;    // 動的配列
    int   m_nNumOf;  // 配列の要素数

    // コンストラクタ・デストラクタ
public:
    explicit CArray(const int nNumOf);
    CArray(const CArray <TYPE> & rother);  // コピーコンストラクタ
    virtual ~CArray();

    // メンバへのアクセス関数
public:
    TYPE Get(const int index) const;
    void Set(const int index, const TYPE value);

    // メンバの参照
    TYPE& operator [](unsigned int index);
    TYPE& operator [](int index);
    TYPE operator [](unsigned int index) const;
    TYPE operator [](int index) const;

    operator const TYPE*() const;  // 配列の直接参照

    // インデックスのチェック
private:
    void CheckIndex(const int index) const;

    // その他の情報の取得
public:
    bool IsValid() const;  // m_pnum の値が有効かどうか
    int NumOf() const;     // 配列の要素数
    int SizeOf() const;    // 配列のサイズ

    // コピー
public:
    bool Copy(const CArray <TYPE> & rother);  // 配列のコピー
    CArray <TYPE> & operator =(const CArray <TYPE> & rother);
                                              // = 演算子のオーバーロード

    // 諸関数
private:
    void Init();     // メンバの初期化
    void Release();  // メモリの解放
};

// m_pnum の値が有効かどうか
// inline はやはり template の後に書きます
template <typename TYPE>
inline bool CArray <TYPE> ::IsValid() const
{
    return m_pnum != NULL;
}

// 配列の要素数
template <typename TYPE>
inline int CArray <TYPE> ::NumOf() const
{
    return m_nNumOf;
}

// 配列のサイズ
template <typename TYPE>
inline int CArray <TYPE> ::SizeOf() const
{
    // sizeof を使っていれば、
    // どんな型が来てもきちんとした値が得られます
    return m_nNumOf * sizeof *m_pnum;
}

// 配列の直接参照
// TYPE 型への配列を返すので、
// もちろんキャスト演算子は (const TYPE*) となります
template <typename TYPE>
inline CArray <TYPE> ::operator const TYPE*() const
{
    return m_pnum;
}

// コンストラクタ
template <typename TYPE>
CArray <TYPE> ::CArray(const int nNumOf)
{
    // TYPE 型で new します
    // クラスの配列を作るときでもコンストラクタが呼ばれます
    m_pnum = new TYPE[nNumOf];
    if(m_pnum == NULL)
        m_nNumOf = 0;
    else
        m_nNumOf = nNumOf;

    // 0 での初期化は行わないことにします
    // クラスの配列を扱う際に問題になるからです
}

// コピーコンストラクタ
template <typename TYPE>
CArray <TYPE> ::CArray(const CArray <TYPE> & rother)
{
    Init();
    Copy(rother);
}

// デストラクタ
template <typename TYPE>
CArray <TYPE> ::~CArray()
{
    Release();
}

// メンバへのアクセス関数
template <typename TYPE>
TYPE CArray <TYPE> ::Get(const int index) const
{
    CheckIndex(index);
    return m_pnum[index];
}

template <typename TYPE>
void CArray <TYPE> ::Set(const int index, const TYPE value)
{
    CheckIndex(index);
    m_pnum[index] = value;
}

// インデックスのチェック
template <typename TYPE>
void CArray <TYPE> ::CheckIndex(const int index) const
{
    if((unsigned int)index < (unsigned int)m_nNumOf)
        return;

    cout << "インデックスが不正です!" << endl
         << "値 : " << index << endl;
    exit(1);
}

// メンバの参照
template <typename TYPE>
TYPE& CArray <TYPE> ::operator [](unsigned int index)
{
    CheckIndex(index);
    return m_pnum[index];
}

// メンバの参照
template <typename TYPE>
inline TYPE& CArray <TYPE> ::operator [](int index)
{
    // ちょっと強引でしょうか?
    return (*this)[(unsigned int)index];
}

// メンバの参照
template <typename TYPE>
TYPE CArray <TYPE> ::operator [](unsigned int index) const
{
    CheckIndex(index);
    return m_pnum[index];
}

// メンバの参照
template <typename TYPE>
inline TYPE CArray <TYPE> ::operator [](int index) const
{
    return (*this)[(unsigned int)index];
}

// 配列のコピー
template <typename TYPE>
bool CArray <TYPE> ::Copy(const CArray <TYPE> & rother)
{
    // 自分自身はコピーしない
    if(this == &rother)
        return true;

    Release();  // 配列が確保されているときはメモリを解放

    if(rother.IsValid() == true)
    {
        m_pnum = new TYPE[rother.NumOf()];
        if(m_pnum == NULL)
        {
            m_nNumOf = 0;
            return false;
        }
        m_nNumOf = rother.m_nNumOf;

        // コピーは = 演算子を使って行います
        // クラスを扱うときに問題になるからですね
        for(int i = 0; i < m_nNumOf; i++)
            m_pnum[i] = rother[i];
    }

    return true;
}

// = 演算子によるコピー
// もちろんテンプレート引数は戻り値の型にも必要です
template <typename TYPE>
CArray <TYPE> & CArray <TYPE> ::operator =(const CArray <TYPE> & rother)
{
    Copy(rother);
    return *this;
}

// メンバの初期化
template <typename TYPE>
void CArray <TYPE> ::Init()
{
    m_pnum   = NULL;
    m_nNumOf = 0;
}

// メモリの解放
// 配列が確保されているときだけメモリを解放します
// 解放した後はメンバを初期化します
template <typename TYPE>
void CArray <TYPE> ::Release()
{
    if(IsValid() == true)
    {
        delete [] m_pnum;
        Init();
    }
}

#endif // #ifnde __ARRAY_H__INCLUDED__

Last update was done on 2000.12.7

この講座の著作権はロベールが保有しています