在GameBoard,h文件:
#ifndef _GAMEBOARD_H #define _GAMEBOARD_H #include <iostream> #include <vector> template<typename T> class GameBoard { public: GameBoard(); GameBoard(const T& src); //复制构造函数 GameBoard(size_t inWidth,size_t inHeight); virtual ~GameBoard(); public: void setElemAt(size_t x,size_t y,const T& inElem); const T& getElem(size_t x,size_t y); size_t getWidth(){return mWidth;} size_t getHeight(){return mHeight;} static const size_t mDefaultWidth = 10; static const size_t mDefaultHeight = 10; private: size_t mWidth,mHeight; void copyFrom(const T& src); void initialContainer(); std::vector<std::vector<T>> mCells; }; #endif //_GAMEBOARD_H
在GameBoard.cpp文件里:
#include "GameBoard.h" template<typename T> GameBoard<T>::GameBoard() :mWidth(0) ,mHeight(0) { initialContainer(); } template<typename T> GameBoard<T>::GameBoard(const T& src) :mWidth(src.mWidth) ,mHeight(src.mHeight) { copyFrom(src); } template<typename T> GameBoard<T>::GameBoard(size_t inWidth,size_t inHeight) :mWidth(inWidth > mDefaultWidth ? mDefaultWidth : inWidth) ,mHeight(inHeight > mDefaultHeight ? mDefaultHeight : inHeight) { initialContainer(); } template<typename T> GameBoard<T>::~GameBoard() { } template<typename T> void GameBoard<T>::setElemAt(size_t x,size_t y,const T& inElem) { mCells[x][y] = inElem; } template<typename T> const T& GameBoard<T>::getElem(size_t x,size_t y) { return mCells[x][y]; } template<typename T> void GameBoard<T>::copyFrom(const T& src) { mWidth = src.mWidth; mHeight = src.mHeight; initialContainer(); for(int i = 0;i < mWidth;++i) { for(int j = 0;j < mHeight;++j) { mCells[i][j] = src.mCells[i][j]; } } } template<typename T> void GameBoard<T>::initialContainer() { mCells.resize(mWidth); for(auto &item : mCells) { item.resize(mHeight); } }
在main函数里:
#include <iostream> #include <initializer_list> #include "GameBoard.h" #include "GameBoard.cpp" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char** argv) { GameBoard<int> myIntGameBoard(10,10); for(size_t i = 0;i < myIntGameBoard.getWidth();++i) { for(size_t j = 0;j < myIntGameBoard.getHeight();++j) { myIntGameBoard.setElemAt(i,j,i*10+j); } } for(size_t i = 0;i < myIntGameBoard.getWidth();++i) { for(size_t j = 0;j < myIntGameBoard.getHeight();++j) { std::cout << myIntGameBoard.getElem(i,j) << " "; } std::cout << std::endl; } return 0; }
其意思就是在mCells里插入数据0~99;并且打印出来;
1>不仅仅可以实例化int型的,还可以实例化double,char,int*,char*等等;
如果想将GameBoard对象作为参数,则这样声明:
void myTemplateFirstFun(GameBoard<int>& inGameBoard)
{
//omitted for brevity
}
2>为了书写不那么难看和艰难,可以指定一个更加简单的名字:
typedef GameBoard<int> IntGameBoard
void myTemplateFirstFun(IntGameBoard& inGameBoard)
{
//omitted for brevity
}
3>还可以实例化一个类:
假设Sheepcell是一个类:
GameBoard<Sheepcell> mySheepCellBoard;
Sheepcell myCell("Text");
mySheepCellBoard.setElemt(0,0,myCell);
4>还可以保存指针
GameBoard<const char *> charGameBoard;
charGameBoard.setElemt(0,0,"hello");
5>指定的类型甚至可以是一个类模板类型:
GameBoard<std::vector<int>> gridGameBoard;
std::vector<int> myIntVector{1,2,3,4};
gridGameBoard.setElemt(1,2,myIntVector);
6>还可以在堆上动态分配GameBoard模板:
auto myGameBoard = std::make_unique<int>(2,2);
myGameBoard ->setElemt(1,2,10);
int x = myGameBoard ->getElemt(1,2);
7>讲解一下编译器处理模板的原理:
- 选择性实例化
比如:
GameBoard<const char *> charGameBoard;
charGameBoard.setElemt(0,0,"hello");
编译器只会为const char *生成无参数的构造函数,析构函数和setElemt()的代码,不会为其他方法生成代码,例如复制构造函数,运算符等等
8>限制模板的实例化
希望类模板采用已知的类型比如:int,double,std::vector;就需要在源文件里显示的实例化模板(在.cpp文件最后写上)
template class GameBoard<int>;
template class GameBoard<double>;
template class GameBoard<std::vector<int>>;
这样就不允许客户用其他类型的实例化了;