[程序6] #include<ioStream.h> template<class T>class Array; template<class T>class ArrayBody{ friend (1) ; T* tpBody; int iRows,iCurrentRow; ArrayBOdy(int iRsz,int iCsz){ tpBody= (2) ; iRows=iRsz,iColumns=iCsz;iCurrentRow=-1; } public: T& operator[](int j) { bool row_error,column_error; row_error=column_error=false; try{ if(iCurrentRow<0||iCurrentRow≥iRows)row_error=; if(j<0|| j≥iColumnscolumn_error=; if(row_error==true || column_error==true) (3) ; } eatch(char) {if(row error==true) cerr<<“行下标越界[“<<iCurrentRow<<”]”;if(column error==true) cerr<<“列下标越界[“<<j<<”]”;cout<<“\n”; } return tpBody[iCurrentRow * iColumns+j];}~ArrayBody(){delere[]tpBody;} }; template<class T>class Array { ArrayBody<T> tBody; public: ArrayBody<T> & operator[](int i){(4) ;return tBody; }; void main() {Array<int> a1(10,20);Array<double> a2(3,5);int b1;double b2;b1=a1[-5][10]; / * 有越界提示:行下标越界[-5] * /b1=a1[10][15]; / * 有越界提示:行下标越界[10] * /b1=a1[1][4]; / * 没有越界提示 * /b2=a2[2][6]; / * 有越界提示:列下标越界[6] * /b2=a2[10][20]; / * 有越界提示:行下标越界[10]列下标越界[20] * /b2=a2[1][4]; / * 没有越界提示 * / }
参考答案:
解析:class Array<T> (2)new T[iRsz * iCsz] (3)throw’e’(注意:throw后可以填写任意的字符常数) (4)tBody.iCurrentRow=i (5)tBody(iRsz,iCsz)
[分析]: 程序中使用了类模板和友元。首先简单地介绍这2个概念。 模板可以实现逻辑相同、数据类型不同的程序代码的复制,模板机制可以减轻编程和维护的工作量和难度。模板可以分为函数模板和类模板,类模板的一般定义形式 template<类型形参表>class类名{类声明体} 在所有出现类模板的地方不能直接用类名表示,需要加上<类型形参表)。 友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,说明时在前面加关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。 友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。 本题中,(1)空的前面是友元关键词friend,但程序中没有独立的函数,所以只能是另一个模板类Array,所以(1)空应填class Array<T>。 在类模板ArrayBody的定义中,声明了成员变量“T tpBody”,且在析构函数中有“delete[]tpBody”,因为在C++中,delete总是和new成对出现,所以(2)空应该使用 new对tpBody进行初始化。通过return tpBody[iCurrentRow * iColumns+j]行,可知该题中采用一维数组来模拟二维数组的创建。在构造函数有2个参数,分别为行数和列数,所以(2)空应填new T[iRsz*iCsz]。 (3)空的前后有try{...}和catch{...}语句序列,这是C++中典型的异常处理搭配语句。 因为(3)空前面已做处理,当有行下标越界时,置row_error=True;当有列下标越界时,置col_error=True。(3)空前面的判断是“row_error==True||column_error== True”,即只要有行下标越界或是列下标越界就执行(3)空。错误处理语句早已写好,放在catch中。catch是当正常程序段发生异常时才执行的,并且这里指明了是catch (char),所以只要在(3)空处抛出一个char异常,即可进行错误处理。所以(3)空应填 throw’e’,(这里可以是任何字符)。 下面再填Array类中的2个空。首先看(5)空,这显然是做一些初始化工作,给其成员变量赋初值,而Array类只有1个成员变量tBody,且tBody是ArrayBody类型的, ArrayBody的构造函数需要传递2个参数,分别代表数组的行和列。因此(5)空应填 tBody(iRsz,iCsz)。 main中实例化Array,而在类Array的构造函数对tBody这个变量进行实例化,这时就以一维数组的形式创建了二维数组。在类Array中门运算符重载函数中返回了一个 ArrayBody类,而在ArrayBody也存在着口运算符重载函数,并且在ArrayBody的重载函数中对行下标和列下标同时进行了检查,且返回了一个T类型,对Array<int>来说就是返回了int,也就是数组的一个元素。通过对类ArrayBody的观察,发现在整个 ArrayBody中并没有任何地方对iCurrentRow进行赋值,而在ArrayBody的[]运算符重载中却利用其对数组行下标进行判断,而数组的行下标只在Array的口运算符重载中出现,那么(4)空就应该是对类ArrayBody的成员变量iCurrentRow进行赋值,所以(4)空应填tBody.iCurrentRow=i。