[]運算子的重載和二維數組類的[][]運算子多載

來源:互聯網
上載者:User

微軟的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]的引用,也就是得到了記憶體中儲存資料的實際位置,最終賦值操作把資料注入正確的記憶體位置。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.