クラスメモPart1-2

Part1をテンプレートで書いてみる。

#ifndef INCLUDED_ARRAY2D_H__
#define INCLUDED_ARRAY2D_H__

template <typename TYPE> 
class Array2D {
public:
	Array2D(int i,int j);
	~Array2D();
	void Show(); //表示させる関数
	TYPE& operator()(int i, int j); //参照つけないと、代入の時「式は変更可能な左辺値である必要があります」と出てくる。
private:
	TYPE* mArray;
	int mRow; //行
	int mCol; //列

};

#include "GameLib/Framework.h"
//#include "Array2D.h"
using namespace GameLib;


template <typename TYPE>
Array2D<TYPE>::Array2D(int i,int j) : mRow(i), mCol(j),mArray(0) {
	mArray = new TYPE[mRow*mCol];
}

template <typename TYPE>
Array2D<TYPE>::~Array2D() {
	delete[] mArray;
	mArray = 0;
	
}

template <typename TYPE>
void Array2D<TYPE>::Show() {
	for(int i=0;i<mRow;i++) {
		for(int j=0;j<mCol;j++) {
			cout << this->operator()(i,j) << "a"; //呼び出されたインスタンスtestのtest(i,j)を返す。
		}
		cout << endl;
	}
}

template <typename TYPE>
TYPE& Array2D<TYPE>::operator()(int i,int j) {
	return mArray[i*mCol+j];
	//mArray[i*mCol+j]を値戻しではなく、エイリアスをつくって、そっくりそのまま渡す。
	//書き込まれる時は、mArray[i*mCol+j]の箱に書き込まれ、(このことから、関数の後ろにconstを付けてはならない。)
	//読み込まれる時は、mArray[i*mCol+j]の値を参照する。
}

#endif

注意:テンプレートの実装と宣言は分離できない。vc++がtemplateに関してはinclusion-modelを採用しているため、実体化したいtemplateの実装はheaderに書かなければならない。(詳しくはよくわからない。)
インラインにする必要のないとき、

template <typename TYPE>
TYPE& Array2D<TYPE>::operator()(int i,int j) {
//
}

という風にかく。特にArray2D::operator()(int i,int j)の部分のを書き漏らすことが多いので気を付ける。

テンプレートってできることの幅がかなり増える割に書き方が恐ろしく単純だよね。
でも、クラスの顔であるヘッダーに見せるのだから、バグが起こったときに問題を発見するのが難しいという欠点がありそう。