[]运算符的重载和二维数组类的[][]运算符重载

微软的MFC框架中的CWordArray、CByteArray等一些类提供了一套用面向对象机制封装的数组类,使用起来非常方便,相当于VB中的变长数组,而且由于完善的封装,免去了用标准C++的new方法分配内存的操作,避免了因为忘记delete内存而造成内存泄漏的情况发生(前提是这些类的实例是在栈上创建,不是在堆上创建)。由于这些类重载了[]运算符,使得我们不必非要使用蹩脚的SetAt(),GetAt()来访问数组元素,我们完全可以象使用普通数组一样通过方括号[]来访问C**Array的元素。下段代码简要演示了这种使用方法: 
 
 CString s;
 CWordArray cwarr;
 cwarr.SetSize(1000);
 cwarr[100]=90;   //能够这样使用得益于[]运算符的重载。
 s.Format("%d",cwarr[100]);  //能够这样使用得益于[]运算符的重载。
 AfxMessageBox(s);

在微软的头文件afxcoll.h里CWordArray定义里可以看到如下声明:

 // overloaded operator helpers
 WORD operator[](int nIndex) const;
 WORD& operator[](int nIndex);

这便是运算符重载的申明。CWordArray的代码是看不到的。但仿造CWordArray简单的写一个一维WORD数组类并实现[]运算符的重载并不难,代码如下:

-------------------------------------------------------------------------------------
//一维WORD数组
class CWordArr
{
private:
 WORD *m_pdat;
 long m_size;
public:
 CWordArr(long size)
 {
  m_pdat= new WORD[size];
  m_size = size;
 };
 ~CWordArr()
 {
  delete[] m_pdat;
 };
 WORD& operator[](long idx)
 {
  return m_pdat[idx];
 }
};

-------------------------------------------------------------------------------------

运算符的重载可以看作是一个做了语法修饰的成员函数,可以看作是一种函数调用的方式,它提供了语法上的方便(参考自:《C++编程思想》一书)。cwarr[100]=90; 这一句代码之所以能够执行,就在于这句代码其实调用了WORD& operator[](long idx)这个成员函数(姑且叫做成员函数吧),这个函数把m_pdat[idx]当作一个WORD型的引用返回了,就等于暂时给m_pdat[idx]申明了一个引用,所以赋值操作就等于给这个临时的WORD型引用进行赋值,结果就是把90这个值注入了m_pdat[idx]这块内存中,这句代码执行完毕后,临时的引用会被销毁。这就是整个运算符重载的运行机理。

一维数组类的[]运算符重载并不难,最近为了优化一个算法,自己写了一个二维数组类,突发奇想,能不能重载[][]运算符呢,这样就可以不用GetAt()SetAt()这些蹩脚的成员函数了。直到看了《C++编程思想》一书的运算符重载那一章,才发现自己对C++的了解还太不够深入,想法比较幼稚,C++不会直接提供[][]的重载的,否则的话相当于重载一个三元运算符,C++里还从未出现过任何三元运算符,三元运算符也没有存在的意义,因为二元运算的叠加可以实现任意元的运算。同样,所谓的[][]的重载,也必须通过两次[]重载的叠加来实现。所以不可能在一个类里面实现[][]的重载,必须有两个类,一个是一维数组类,实现[]的重载,另一个类是二维数组类,必须持有一组一维数组类的实例,存放二维数组的各个行的数组,二维数组类也要重载[]运算符,这样,通过两次[]重载的叠加,就可以用a[x][y]的方式来访问数组元素了。
代码如下:

--------------------------------------------------------------------------------------

//一维WORD数组
class CWordArr
{
private:
 WORD *m_pdat;
 long m_size;
public:
 CWordArr(long size)
 {
  m_pdat= new WORD[size];
  m_size = size;
 };
 ~CWordArr()
 {
  delete[] m_pdat;
 };
 WORD& operator[](long idx)
 {
  return m_pdat[idx];
 }
};

//二维WORD数组
class C2DimWordArr
{
private:
 CWordArr **m_p;//主指针
 long m_row,m_column;//行数,列数。

public:
 C2DimWordArr(long row,long column)
 {
  m_p=new CWordArr*[row];
  for (long i=0;i<row;i++)
  {
   m_p[i]= new CWordArr(column);
  }
  m_row=row;
  m_column=column;
 }
 ~C2DimWordArr()
 {
  for (long i=0;i<m_row;i++)
  { 
   delete m_p[i];
   m_p[i]=NULL;
  }
  delete[] m_p;
 }
 CWordArr& operator[](long idx)
 {
  return *m_p[idx];
 }
};

--------------------------------------------------------------------------------------
主调代码如下,验证类的正确性:
--------------------------------------------------------------------------------------
 C2DimWordArr c2dwa(4,3);
 long i,j;
 for (i=0;i<4;i++)
  for (j=0;j<3;j++)
   c2dwa[i][j]= i*10 + j ;

 CString s,stmp;
 for (i=0;i<4;i++)
  for (j=0;j<3;j++)
  {
   stmp.Format("[%d][%d] =  %d /n", i,j,c2dwa[i][j]) ;
   s+=stmp;
  }
 AfxMessageBox(s);
--------------------------------------------------------------------------------------
代码的运行机理是这样,当c2dwa[i][j]= i*10 + j ;这句代码执行的时候,(c2dwa[i])先进行语义上的结合,执行了二维数组类的[]重载函数,得到了一个一维数组的引用,假设这个引用叫做b,接着b[j]进行结合,最终得到了m_pdat[idx]的引用,也就是得到了内存中存储数据的实际位置,最终赋值操作把数据注入正确的内存位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值