题目一:C++ 类的一个关键性质是:“接口”与“实现”的分离。所谓接口是一组操作行为,用户可以将它施行于此类所派生的任何对象身上。它由三个部分组成:操作名称,返回值,参数列表。一般而言,类的用户只需要知道这些就够了。而私底下的实现内容(方法的具体代码),由算法和数据构成。观念上,虽然类的接口可以成长,却不可以改头换面变得与过去版本不兼容。置于死地下的实现内容,则可以自由演化。现在,请选择以下一个抽象性事物,写出其public接口:
Matrix Person Pointer Boolean Date Point
我们选择Matrix(矩阵)来写它的public接口。
class Matrix
{
public:
Matrix(int=defaultRowSize,int=defaultColumnSize);//default constructor。假设defaultRowSize和defaultColumnSize都已被定义
Matrix(const Matrix &);//copy constructor
~Matrix();//destructor
Matrix &operator=(const Matrix &);//copy assignment operator 赋值运算
bool operator==(const Matrix &)const;//equality operator
bool operator!=(const Matrix&)const;//inequality operator
int &operator()(int,int);//indexing operator
int operator()(int,int)const;//indexing operator
int getRowSize()const;//number of rows
int getColumnSize()const;//number of columns
friend ostream &operator<<(ostream&,const Matrix &);//iostream output operator
friend istream &operator>>(istream&,Matrix &);//iostream input operator
private:
int**im; //implementation
int rows; //how many rows
int cols; //how many columns
static const int default RowSize=5;
static const int defaultColumnSize=5;
void initMatrix(int*);//init with a row
void initMatrix(int **);//init with a matrix
void initData(int r,int c);
};
关于Matrix类,我们提供了两个构造函数,default constructor和copy constructor。并且提供了一个析构函数~Matrix()。并且提供了一些运算符的重载函数,比如赋值,比较,之类的。这就是一个较为完整合理的接口了。
习题二:
constructor(构造函数)和destructor(析构函数)这两个字眼,在那些“由程序员供应,既不做构造行为也不做析构行为”的诸多函数中,显得有点令人迷惑。当我写下 :
int main()
{
IntArray my Array(1024);
//……
return 0;
}
时,myArray data members所需要的内存,在constructor被调用之前就已经分配好了,事实上编译器将我的代码暗中转换为(注意,以下并非合法的C++程序代码);
int main()
{
IntArray my Array;
//C++伪码---调用constructor
myArray.IntArray::IntArray(1024);
//……
//C++伪码-----调用destructor
myArray.IntArray::~IntArray();
return 0;
}
class的constructor主要用来为class object(对象)的成员数据(data members)设定初值,而destructor的主要用途是释放class object生命期间分配到的任何资源。请问上一题所选择的class定义一组必要的constructor。这个class是否需要一个destructor呢?
构造函数:
Matrix(int=defaultRowSize,int=defaultColumnSize);//default constructor。假设defaultRowSize和defaultColumnSize都已被定义
Matrix(const Matrix &);//copy constructor
析构函数:
~Matrix();//destructor
我们需要一个destructor,因为Matrix有个指针形式的data member,记住,如果class需要一个copy constructor,一个copy assignment operator,或是一个destructor。它大约也就同时需要三者。如果class内有(至少)一个指向某块heap内存的指针,该内存在class constructor内分配,需由destructor释放,那么该class便需要上述三个函数。
习题三:写出上述的那些函数的实现
首先,是private member function initData(),他被constructor调用
void Matrix::initData(int r,int c)
{
rows=r;
cols=c;
}
其次,是两个private member function initMatrix()
void Matrix::initMatrix(int *array)
{
for(int i=0;i<rows;++i)
{
for(int j=0;j<cols;++j)
{
if(array)
im[i][j]=*array++;
else [i][j]=0;
}
}
}
void Matrix::initMatrix(int**matrix)
{
for(int i=0;i<rows;++i)
for(int j=0;j<cols;++j)
im[i][j]=matrix[i][j];
}
下面是default constructor的实现代码:
Matrix::Matrix(int r,int c)
{
iniitData(r,c);
initMatrix(static_cast<int*>(0));
}
第二个constructor
Matrix::Matrix(int r,int c,int *array)
{
initData(r,c);
initMatrix(array);
}
下面是copy constructor
Matrix::Matrix(const Matrix &rhs)
{
initData(rhs.rows,rhs.cols);
initMatrix(rhs.im);
}
下面是destructor
Matrix::~Matrix()
{
for(int i=0;i<rows;++i)
delete[]im[i];
delete[]im;
}
下面是copy assignment操作符
Matrix &Matrix::operator=(const Matrix &rhs)
{
if(this!=&rhs)
{
if(rows!=rhs.rows||cols!=rhs.cols)
{
Matrix::~Matrix();
initData(rhs.rows,rhs,cols);
}
initMatrix(rhs.im);
}
return *this;
}
此外,我还提供了一个Fortran风格的index操作符给Matrix使用
int &Matrix::operator[](int r,int c)
{
assert(r>=0&&r<rows&&c>=0&&c<cols);
return im[r][c];
}
const int &Matrix::operator[](int r,int c)const
{
assert(r>=0&&r<rows&&c>=0&&c<cols);
return im[r][c];
}