读书人

C++技巧二维动态数组类模板

发布时间: 2009-04-28 22:57:53 作者: liuhuituzi

C++提供了许多强大的机制来实现代码的高度复用、来使我们使用我们自已的类就像使用内置类型那样方便快捷。比如模板,运算符重载等等。模板好比如是一个大批量生产函数和类的工厂,使我们不用再去关心与数据类型相关的繁琐编程细节,把我们精力留给那些真正值得我们去认真思考的地方。而运算符重载则使我们的程序更直观更简洁,这不仅使我们更容易读懂我们的程序,而且使我们能以一种更为流畅的方式来表达我们的想法。就像上篇文章说到的,如果我们把动态分配的二维数组用类模板实现,并重载相应的操作符,我们就能十分方便的使用我们自己定义的数组类型了。今天我正好把以往的程序整理了一下,就一并贴了出来,看下面的程序。下面的两个类模板在vc++6.0上编译运行良好,测试程序也都得到正确的结果,如果在其他编译环境下有什么问题,欢迎给我留言。
  第一个头文件Array.h是一维动态数组类模板:
  //Array.h
  #ifndef CARL_SEN_ARRAY_H
  #define CARL_SEN_ARRAY_H
  #include <iostream>
  #include <cstdarg>
  using std::out_of_range;
  using std::ostream;
  template<typename T>
  class Array {
  protected:
  unsigned int size;
  T* data;
  public:
  //构造函数
  Array(unsigned int _size=0);
  Array(unsigned int count, T data1, ...);
  //复制控制
  Array(const Array<T>& array);
  Array& operator=(const Array<T>& array);
  ~Array() {
  delete[] data;
  }
  //两种重载运算符
  T& operator[](unsigned int index);
  const T& operator[](unsigned int index) const;
  friend ostream& operator<<(ostream& os, const Array<T>& array);
  //get,set成员函数
  unsigned int getSize() const {
  return size;
  }
  void setSize(unsigned int newSize);
  };
  template <typename T>
  Array<T>::Array(unsigned int _size):data(new T[_size]), size(_size) {
  for(unsigned int i=0; i<size; ++i) {
  data[i]=T();
  }
  }
  template <typename T>
  Array<T>::Array(unsigned int count, T data1, ...):size(count), data(new T[count]) {
  va_list ap;
  va_start(ap, count);
  for(unsigned int i=0; i<size; ++i) {
  data[i]=va_arg(ap, T);
  }
  va_end(ap);
  }
  template <typename T>
  Array<T>::Array(const Array<T>& array):size(array.size), data(new T[array.size]) {
  for(unsigned int i=0; i<size; ++i) {
  data[i]=array.data[i];
  }
  }
  template <typename T>
  Array<T>& Array<T>::operator=(const Array<T>& array) {
  if(&array!=this) {
  delete[] data;
  data=new T[array.size];
  size=array.size;
  for(unsigned int i=0; i<size; ++i) {
  data[i]=array.data[i];
  }
  }
  return *this;
  }
  template <typename T>
  T& Array<T>::operator[](unsigned int index) {
  if(index>=size) {
  throw out_of_range("invalid index");
  }
  return data[index];
  }
  template <typename T>
  const T& Array<T>::operator[](unsigned int index) const {
  if(index>=size) {
  throw out_of_range("invalid index");
  }
  return data[index];
  }
  template <typename T>
  void Array<T>::setSize(unsigned int newSize) {
  T* const newData=new T[newSize];
  const unsigned int Min=size<newSize?size:newSize;
  for(unsigned int i=0; i<Min; ++i) {
  newData[i]=data[i];
  }
  delete[] data;
  data=newData;
  size=newSize;
  }
  template <typename T>
  ostream& operator<<(ostream& os, const Array<T>& array) {
  for(int i=0; i<array.size; ++i) {
  os<<array.data[i]<<"\t";
  }
  return os;
  }
  #endif

第二个头文件Array2D.h是二维动态数组类模板:
  //Array2D.h
  #ifndef CARL_SEN_ARRAY2D_H
  #define CARL_SEN_ARRAY2D_H
  #include "Array.h"
  #include <iostream>
  #include <cstdarg>
  using std::ostream;
  using std::out_of_range;
  template <typename T>
  class Array2D {
  protected:
  unsigned int rows;
  unsigned int cols;
  Array<T> array;
  public:
  //构造函数
  Array2D(unsigned int _rows=0, unsigned int _cols=0);
  Array2D(unsigned int _rows, unsigned int _cols, T data1, ...);
  //两种重载运算符
  class RowArray;
  RowArray operator[](unsigned int row);
  const RowArray operator[](unsigned int row) const;
  friend ostream& operator<<(ostream& os, const Array2D<T>& array2D);
  //计算第二维下标操作的嵌套类
  class RowArray {
  private:
  const Array2D<T>& array2D;
  unsigned int row;
  public:
  RowArray(Array2D<T>& _array2D, unsigned int _row=0):
  array2D(_array2D), row(_row) {}
  RowArray(const Array2D<T>& _array2D, unsigned int _row=0):
  array2D(_array2D), row(_row) {}
  T& operator[](unsigned int col) {
  if(col>=array2D.cols) {
  throw out_of_range("invalid col");
  }
  return const_cast<Array2D<T>&>(array2D).array[row*array2D.cols+col];
  }
  const T& operator[](unsigned int col) const {
  if(col>=array2D.cols) {
  throw out_of_range("invalid col");
  }
  return array2D.array[row*array2D.cols+col];
  }
  };
  friend class RowArray;
  //get,set函数
  unsigned int getRows() const {
  return rows;
  }
  unsigned int getCols() const {
  return cols;
  }
  };
  template <typename T>
  Array2D<T>::Array2D(unsigned int _rows, unsigned int _cols):
  rows(_rows), cols(_cols), array(_rows*_cols){
  for(unsigned int i=0; i<rows*cols; ++i) {
  array[i]=T();
  }
  }
  template <typename T>
  Array2D<T>::Array2D(unsigned int _rows, unsigned int _cols, T data1, ...):
  rows(_rows), cols(_cols),array(_rows*_cols){
  va_list ap;
  va_start(ap, _cols);
  for(unsigned int i=0; i<rows*cols; ++i) {
  array[i]=va_arg(ap, T);
  }
  va_end(ap);
  }
  template <typename T>
  Array2D<T>::RowArray Array2D<T>::operator[](unsigned int row) {
  if(row>=rows) {
  throw out_of_range("invalid row");
  }
  return RowArray(*this, row);
  }
  template <typename T>
  const Array2D<T>::RowArray Array2D<T>::operator[](unsigned int row) const {
  if(row>=rows) {
  throw out_of_range("invalid row");
  }
  return RowArray(*this, row);
  }
  template <typename T>
  ostream& operator<<(ostream& os, const Array2D<T>& array2D) {
  unsigned int i, j;
  for(i=0; i<array2D.rows; ++i) {
  for(j=0; j<array2D.cols; ++j) {
  os<<array2D.array[i*array2D.cols+j]<<"\t";
  }
  if(i!=array2D.rows-1) {
  os<<endl;
  }
  }
  return os;
  }
  #endif
  现在就可以使用它们了,如下面的测试程序:
  #include "Array.h"
  #include "Array2D.h"
  #include <iostream>
  #include <string>
  using std::string;
  using std::cout;
  using std::endl;
  void testArray();
  void testArray2D();
  int main() {
  testArray();
  testArray2D();
  return EXIT_SUCCESS;
  }
  void testArray() {
  //普通数组
  Array<int> a1(3);
  cout<<"Testing Array: print 1"<<endl;
  cout<<a1<<endl; //整体打印
  unsigned int i;
  for(i=0; i<a1.getSize(); ++i) {
  a1[i]=i+1; //逐个赋值
  }
  cout<<"Testing Array: print 2"<<endl;
  for(i=0; i<a1.getSize(); ++i) {
  cout<<a1[i]<<"\t"; //逐个打印
  }
  cout<<endl;

//常量数组
  const Array<int> a2(3, 123, 234, 345);
  cout<<"Testing Array: print 3"<<endl;
  cout<<a2<<endl;
  cout<<"Testing Array: print 4"<<endl;
  for(i=0; i<a2.getSize(); ++i) {
  cout<<a2[i]<<"\t";
  }
  cout<<endl;
  //拷贝构造
  Array<int> a3(a1);
  cout<<"Testing Array: print 5"<<endl;
  cout<<a3<<endl;
  const Array<int> a4(a2);
  cout<<"Testing Array: print 6"<<endl;
  cout<<a4<<endl;
  //数组赋值给数组
  Array<int> a5;
  a5=a4;
  cout<<"Testing Array: print 7"<<endl;
  cout<<a5<<endl;
  //增减数组元素
  a5.setSize(a5.getSize()+1);
  a5[a5.getSize()-1]=111;
  cout<<"Testing Array: print 8"<<endl;
  cout<<a5<<endl;
  a5.setSize(a5.getSize()-2);
  cout<<"Testing Array: print 9"<<endl;
  cout<<a5<<endl;
  //保存对象
  Array<string> a6(2, string("str0"), string("str1"));
  cout<<"Testing Array: print 10"<<endl;
  cout<<a6<<endl;
  for(i=0; i<a6.getSize(); ++i) {
  a6[i]+=static_cast<char>(48+i);
  }
  cout<<"Testing Array: print 11"<<endl;
  for(i=0; i<a6.getSize(); ++i) {
  cout<<a6[i]<<"\t";
  }
  cout<<endl;
  const Array<string> a7(3, string("000"), string ("111"), string("222"));
  cout<<"Testing Array: print 12"<<endl;
  cout<<a7<<endl;
  for(i=0; i<a7.getSize(); ++i) {
  cout<<a7[i]<<"\t";
  }
  cout<<endl;
  }
  void testArray2D() {
  //普通数组
  Array2D<int> a1(2, 2);
  cout<<"Testing Array2D: print 1"<<endl;
  cout<<a1<<endl;
  unsigned int i,j;
  for(i=0; i<a1.getRows(); ++i) {
  for(j=0; j<a1.getCols(); ++j) {
  a1[i][j]=i+j;
  }
  }
  cout<<"Testing Array2D: print 2"<<endl;
  for(i=0; i<a1.getRows(); ++i) {
  for(j=0; j<a1.getCols(); ++j) {
  cout<<a1[i][j]<<"\t";
  }
  cout<<endl;
  }
  //常量数组
  const Array2D<int> a2(2, 2, 123, 234, 345, 456);
  cout<<"Testing Array2D: print 3"<<endl;
  cout<<a2<<endl;
  cout<<"Testing Array2D: print 4"<<endl;
  for(i=0; i<a2.getRows(); ++i) {
  for(j=0; j<a2.getCols(); ++j) {
  cout<<a2[i][j]<<"\t";
  }
  cout<<endl;
  }
  //拷贝构造
  Array2D<int> a3(a1);
  cout<<"Testing Array2D: print 5"<<endl;
  cout<<a3<<endl;
  const Array2D<int> a4(a2);
  cout<<"Testing Array2D: print 6"<<endl;
  cout<<a4<<endl;
  //数组赋值给数组
  Array2D<int> a5;
  a5=a4;
  cout<<"Testing Array2D: print 7"<<endl;
  cout<<a5<<endl;
  //保存对象
  Array2D<string> a6(2, 2, string("str00"), string("str01"), string("str10"), string("str11"));
  cout<<"Testing Array2D: print 8"<<endl;
  cout<<a6<<endl;
  for(i=0; i<a6.getRows(); ++i) {
  for(j=0; j<a6.getCols(); ++j) {
  a6[i][j]+=static_cast<char>(48+i+j);
  }
  }
  cout<<"Testing Array2D: print 9"<<endl;
  for(i=0; i<a6.getRows(); ++i) {
  for(j=0; j<a6.getCols(); ++j) {
  cout<<a6[i][j]<<"\t";
  }
  cout<<endl;
  }
  const Array2D<string> a7(2, 1, string("11111"), string("22222"));
  cout<<"Testing Array2D: print 10"<<endl;
  cout<<a7<<endl;
  cout<<"Testing Array2D: print 11"<<endl;
  for(i=0; i<a7.getRows(); ++i) {
  for(j=0; j<a7.getCols(); ++j) {
  cout<<a7[i][j]<<"\t";
  }
  cout<<endl;
  }
  }

3COME考试频道为您精心整理,希望对您有所帮助,更多信息在http://www.reader8.net/exam/

读书人网 >复习指导

热点推荐