第四十二讲 深入class(5)

      深入class这一讲我们说了不少天了,今天我们来把他结束吧,也该是结束的时候了,通过这个电子表格开发的例子,大家现在已经明白了一件事,那就是C++的class也不是太难,只要大家新村对象之念便可一一定义出来,就好比我们在第四十讲里说的一样,在C程序里面,我们会按过程式的方式来描述,但当我们用C++来写的时候,我们会把时间当成一个对象,而时针和分针之间的夹角不过只是这个对象的一个属性而已。
现在我们来再来看看我们下面这个类,这是我们的电子表格的最终版本:
——————————————
#include “SpreadSheetData”
namespace My_Code{
class SpreadSheet
{
public:
SpreadSheet(int width,int high);

SpreadSheet(const SpreadSheet &

Data);

virtual ~SpreadSheet();

SpreadSheet&

operator=(const SpreadSheet &

Data);

void SetCellAt(int x,int y,const SpreadSheetCell&

Cell);

SpreadSheetCell&

GetCell(int x,int y);

protected:
SpreadSheetData *m_Data;

};

}
————————————–
      大家也看到了,我们最终的Spreadsheet和SpreadsheetData有些像,其实不是有些像啦,他们的方法都是一样的,我们可以像使用SpreadSheetData一样使用他:
————————————-
f()
{
         SpreadSheet myData(3,4);

myData.SetCellAt(2,2,6);


}
——————————————
      像第四十一讲里面的一样,我们可以得到同样的结果。
      那么现在大家是不是很好奇,为什么我们要把相同的两种方法实现两边呢?如果大家真有这种想法的话,我们可以来看下我们今天界面的实现方案:
——————————————
#include “Spreadsheet.h”
using namespace My_Code;


SpreadSheet::SpreadSheet(int width,int high)
{
m_Data = new SpreadSheetData(width,high);

}
SpreadSheet::~SpreadSheet()
{
m_Data->~SpreadSheetData();

}
SpreadSheet::SpreadSheet(const SpreadSheet&

Data)
{
m_Data = new SpreadSheetData(*(Data.m_Data));

}
SpreadSheet&

SpreadSheet::operator=(const SpreadSheet &

Data)
{
*m_Data = *Data.m_Data;

return *this;

}

void SpreadSheet::SetCellAt(int x,int y,const SpreadSheetCell &

cell)
{
m_Data->SetCellAt(x,y,cell);

}
SpreadSheetCell&

SpreadSheet::GetCell(int x,int y)
{

return m_Data->GetCell(x,y);

}
——————————————-
现在大家是不是有种如梦方醒的感觉呢?从表面上看上去,我们好像要将相同的方法实现两边,但实际上我们只是去调用我们已经准备好的方案,为什么要这样呢?因为这样更能体现出oo思想,将数据和方法彻底分离出来。
现在回来看看上面的实现,首先是构造函数,有些朋友可能想,为什么不直接去调用要重新new一个出来呢?哦,对了,既然大家发现了那我就只好告诉大家,因为对象是不能够调用就能够出来,那只是方法,要产生一个对象怎么办?必须得创建出来,创建一个对象我们需要相应的内存,而new不但可以动态分配内存,还能够创建出相应的对象,这就是为什么C++里面没人用malloc都用new的原因。
第二个大家可能觉得有些奇怪的地方:*m_Data = *Data.m_Data;

大家是不是想问,为什么不是m_Data = Data.m_Data呢?原因很简单,因为这样写的话其实只是将地址传递过去,也就是说,两个m_Data共同指向一块内存块,这样做极其危险,如果一旦某一边收回这块内存,那么另一边就指空,所以,我们要的不是复制地址,而是复制数据。
除了这两点可能让有部分朋友觉得疑惑之外想必没有啥问题了,那么现在我们重新回到昨天我们遗留下来的问题上来,关于这个辅助函数CopyFrom,难道大家都没有什么想法吗?是啊,不过只是个辅助函数而已,有没有其实没关系,不过就是多敲几句代码而已。
为什么我们引入这个辅助函数呢?大家应该注意到了,在第四十一讲的内容里面有几个函数使用到了相同的代码段,比如,赋值函数,复制构造函数:
————————————–
       m_width = Data.m_width;

m_high = Data.m_high;

m_Cell = new SpreadSheetCell*[m_width];

for(int i=0;

i<m_width;

i++)
m_Cell[i] = new SpreadSheetCell[m_high];

for(int i=0;

i<m_width;

i++)
for(int j=0;

j<m_high;

i++)
m_Cell[i][j] = Data.m_Cell[i][j];


———————————————-
上面这段代码如果我们稍加留意的话会发现好几处都在使用,既然如此,我们何不使用一个辅助函数来实现呢?我们只需要调用这个函数就好,这样一来,整个代码块看上去就比较干净利落了。所以,这里就是我们CopyFrom的实现。
接下来,大家思考一个问题,如果我们要开发一个人事管理系统,我们该怎么着手?

发表评论