第五十二讲 类模板(1)

 

 

 

 

 

说着说着又说跑题了,嗯,虽然扯得有些远了,不过还好被我及时发现,终于拉扯回来,为什么呢?因为啊,private继承真心没啥好说的,而且很多书都没有专门的讲解,可见他的实用性确实不高,但在某些情况下却又还算好用,就像我们上一讲说到的“根据某物实现出”模型,private继承级别比复合还要低,但是当我们要实现的类需要访问基类的protected成员或者重新改写继承而来的virtual函数,那么private继承也有他的好处。

 

 

 

 

 

一句话区分public和private继承,public继承的是接口,而private继承的只是实现,可以根据实际情况而定,不过通常情况如果当你想要用private继承时请三思是不是可以用复合来实现。

 

 

 

 

 

言归正传,我们继续来看看我们的这个问题——关于棋盘的事儿。

 

 

 

 

 

今天我们可以用电子表格来实现一个五子棋的棋盘,那么我们明天是不是还要用这个电子表格来实现一个中国象棋呢?哪有和不可以呢?是啊,当然可以,不过每次想要一个类似的新东西我们就得复合抑或是private一次,那样太过麻烦,现在,我们来看看下面这个如何:

————————————–

template<typename T>
 

class Game{
 

public:
 

 

 

 

 

 

 

 

 

Game(int width,int height);


 

 

 

 

 

 

 

 

 

virtual ~Game();


 

 

 

 

 

 

 

 

 

 

Game(const Game<T>&

);


 

 

 

 

 

 

 

 

 

Game<T>&

operator=(const Game<T>&

rhs);


 

 

 

 

 

 

 

 

 

void SetPiece(int x,int y,const T&

Piece);


 

 

 

 

 

 

 

 

 

T&

GetPieceAt(int x,int y);


 

 

 

 

 

 

 

 

 

 

int GetX(const T&

Piece){

return mx;

}
 

 

 

 

 

 

 

 

 

 

int GetY(const T&

Piece){

return my;

}
 

 

 

 

 

 

 

 

 

 

 

int GetHeight(){
return m_Height;

}
 

 

 

 

 

 

 

 

 

 

 

int GetWidth()
{
return m_Width;

}
 

 

private:
 

 

 

 

 

 

 

 

 

void CopyFrom(const Game&

Data);


 

 

 

 

 

 

 

 

 

int m_Width;


 

 

 

 

 

 

 

 

 

int m_Height;


 

 

 

 

 

 

 

 

 

int mx,my;


 

 

 

 

 

 

 

 

 

T **m_Piece;

 


 

}

———————————–

 

 

 

 

这样一来,我们将这个class模板化,他不但可以表示一个电子表格,还可以表示一切像是表格的东西,甚至可以把一切都装进去,只要我们具体化后,他就能够表示我们想要表示的一切。我们可以像实现SpreadSheetData一样来实现这个模板:

——————————————–

template<typename T>
Game<T>::Game(int width,int height):
 

m_Width(widht),m_Height(height),
 

mx(0),my(0)
{
 

 

 

 

 

 

 

m_Piece = new T*[m_Width];


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

for(int i=0;

i<m_Width;

i++)
 

 

 

 

 

 

 

 

m_Piece[i] = new T[m_High];


}

template<typename T>
Game<T>::~Game()
{
 

 

 

 

 

 

 

for(int i=0;

i<m_Height;

i++)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

delete[] m_Piece[i];


 

 

 

 

 

 

 

 

delete[] m_Piece;


}

template<typename T>

void Game<T>::CopyFrom(const Game<T>&

Data)
{
 

 

 

 

 

 

 

 

m_Width = Data.m_Width;


 

 

 

 

 

 

 

 

m_Height = Data.m_Height;


 

 

 

 

 

 

 

 

m_Piece = new T*[m_Width];


 

 

 

 

 

 

 

 

for(int i=0;

i<m_Width;

i++)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m_Piece[i] = new T[m_Height];


 

 

 

 

 

 

 

 

 

for(int i=0;

i<m_Width;

i++)
 

 

 

 

 

 

 

 

 

 

 

 

 

for(int j=0;

j<m_Height;

j++)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m_Piece[i][j] = Data.m_Piece[i][j];


}

template<typename T>
Game<T>::Game(const Game<T>&

Data)
{
 

 

 

 

 

 

 

CopyFrom(Data);


}

template<typename T>
Game<T>&

Game<T>::operator=(const Game<T>&

Data)
{
 

 

 

 

 

 

 

if(this == &

Data)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

return *this;


 

 

 

 

 

 

for(int i=0;

i<m_Width;

i++)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

delete[] m_Piece[i];


 

 

 

 

 

 

 

delete[] m_Piece;


 

 

 

 

 

 

CopyFrom(Data);


 

 

 

 

 

 

return *this;


}

template<typename T>

void Game<T>::SetPiece(int x,int y,const T&

Piece)
{
 

 

 

 

 

 

mx = x;


 

 

 

 

 

my = y;


 

 

 

 

 

m_Piece[x][y] = Piece;


}

template<typename T>
T&

Game<T>::GetPieceAt(int x,int y)
{
 

 

 

 

 

 

 

return m_Piece[x][y];


}

—————————————-

 

 

 

 

然后我们可以根据我们想要的类型来实例化这个模板,例如:

————————————-

Game<SpreadSheetCell>My_Game(10,10);


Game<int>My_Game2(10,10);

Game<double>My_Game3(10,10);

…………

—————————————-

第五十二讲 类模板(1)

———————————–

 

 

 

今天就说到这里吧,大家可能会遇见一个问题,那就是模板的编译问题,如今对模板的支持大部分的编译器都不怎么好使,所以这个问题留待下一讲吧。

===============

回复D直接查看目录,有问题可以直接提问。

原文始发于微信公众号(

C/C++的编程教室

):第五十二讲 类模板(1)

|

发表评论