017:二维数组类
总时间限制:
1000ms
内存限制:
65536kB
描述
写一个二维数组类 Array2,使得下面程序的输出结果是:
0,1,2,3,
4,5,6,7,
8,9,10,11,
next
0,1,2,3,
4,5,6,7,
8,9,10,11,
程序:
#include <iostream>
#include <cstring>
using namespace std;
class Array2 {
//在此补充你的代码.
};
int main() {
Array2 a(3,4);
int i,j;
for( i = 0;i < 3; ++i )
for( j = 0; j < 4; j ++ )
a[i][j] = i * 4 + j;
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << a(i,j) << ",";
}
cout << endl;
}
cout << "next" << endl;
Array2 b; b = a;
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << b[i][j] << ",";
}
cout << endl;
}
return 0;
}
输入
无
输出
0,1,2,3,
4,5,6,7,
8,9,10,11,
next
0,1,2,3,
4,5,6,7,
8,9,10,11,
样例输入
None
样例输出
0,1,2,3, 4,5,6,7, 8,9,10,11, next 0,1,2,3, 4,5,6,7, 8,9,10,11,
这题没有get到点的话还挺麻烦的。关键在于做一个数组指针的指针。
分析:
1Array2 a(3,4); //构造函数,两int型参数,Array2是二维数组形式。
2a[i][j] = i * 4 + j; //a[i][j] 在C++里相当于:a,operator[](i).operator[](j)
但是用上面说的数组指针的指针则不用这么麻烦,只需重载 “ [ ] ” 即可,详见code。
3cout << a(i,j) << ","; //重载"()",常规操作。
4 b = a; //重载 "=",实现深拷贝。
5 这题不用重载流输入符,因为在 cout<< 这边的都不是类成员变量,是一些类成员函数,在类成员函数里返回能输出的标准值即可。
6常规的复制构造函数(这题用不上,也写写,练手嘛)和析构函数。
完整代码如下:
#include <iostream>
#include <cstring>
using namespace std;
class Array2 {
// 在此处补充你的代码
private:
int ** p;//数组指针的指针,关键!
int col,row;
public:
//构造函数
Array2(int x = 0, int y = 0):col(x),row(y){
if( x && y == 0 ) p = NULL;
else{
p = new int*[col];
for(int i = 0; i < col; i++){
p[i] = new int[row];
}
}
}
//复制构造函数
Array2(const Array2 & array2_){
col = array2_.col;
row = array2_.row;
p = new int*[col];
for(int i = 0; i < col; i++){
p[i] = new int[row];
}
memcpy(p,array2_.p,sizeof(int) * col * row);
}
//重载"="实现深拷贝
Array2 & operator=(const Array2 & array2_){
if(p) delete []p;
col = array2_.col;
row = array2_.row;
p = new int*[col];
for(int i = 0; i < col; i++){
p[i] = new int[row];
}
memcpy(p,array2_.p,sizeof(int) * col * row);
return *this;
}
//析构函数
~Array2(){
if(p) delete []p;
}
//重载"[]"
int * operator[](int i){
return p[i];
//重载的是 a[][]的第一个[] ,因为返回的是p[x],则第二个[]相当于取p[x]的第y个。
}
//重载"()"
int & operator()(int x, int y){ //重载()
return p[x][y];
}
};
int main() {
Array2 a(3,4); //构造函数,两int型参数,Array2是二维数组形式。
int i,j;
for( i = 0;i < 3; ++i )
for( j = 0; j < 4; j ++ )
a[i][j] = i * 4 + j;
//a[i][j] 在C++里相当于:a,operator[](i).operator[](j)
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << a(i,j) << ","; //重载"()"
}
cout << endl;
}
cout << "next" << endl;
Array2 b;
b = a; //重载 "=",实现深拷贝。
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << b[i][j] << ",";
}
cout << endl;
}
return 0;
}
这就是我们今天讲的题,有关运算符重载!
如果大家不了解的话,可以看看下面这个:
运算符重载的注意事项:
-
C++不允许程序员定义新的运算符(废话嘛,运算符已经够多了,还闲不够多吗?不够乱吗?)
-
重载过后的运算符应该符合日常的习惯:什么是日常习惯呢?举几个例子:complex_a+complex_b(我们重载的是加法这个运算符,但是函数里面写的是减法的运算,这就有点儿太坑人了)word_a>word_b(这个重载的是大于号,但是你判断写的是小于)
-
C++里面写运算符重载的时候不能改变运算符计算的优先级
-
还有一些运算符是不能进行重载的,哪些呢:".",".*","::","?:","sizeof"这些都不能进行重载.
-
重载某些运算符的时候,运算符重载函数必须生命为类的成员函数:(),[],->或者赋值运算符=号.
-
运算符重载的实质是将运算符重载为一个函数,使用运算符的表达式就被解释为对“运算符函数”的调用。
-
运算符可以被重载为全局函数,也可以被重载为成员函数。一般来说,倾向于将运算符重载为成员函数,这样能够较好地体现运算符和类的关系。
-
运算符被重载为全局函数时,函数参数的个数就是运算符的操作数个数,运算符的操作数就成为函数的实参。
-
运算符被重载为成员函数时,函数参数的个数就是运算符的操作数个数减一,运算符的操作数有一个成为函数作用的对象,其余的成为函数的实参。
-
必要时需要重载赋值运算符 “=” ,即进行深拷贝,以避免两个对象内部的指针指向同一片存储空间。
-
类型的名字可以作为强制类型转换运算符,也可以被重载为类的成员函数。它能使得对象被自动转换为某种类型。
-
重载运算符时,应该尽量保留运算符原本的用法和特性。例如重载 “+” 运算符,完成的功能就应该类似于做加法,如果在其中做减法就是不合适的;再例如,赋值运算符 “=” ,它是可以连用的,这个特性在重载后也应该保持,所以 operator= 函数一般需要返回其所作用对象的引用,以保持 “=” 连用的这个特性。
-
运算符重载函数不能有默认的参数,否则就改变了运算符操作数的个数,这显然是错误的
-
将运算符重载函数作为类的成员函数时,二元运算符的参数只有一个,一元运算符不需要参数。之所以少一个参数,是因为这个参数是隐含的。
-
除了‘=’运算符以外,其他的运算符重载最好设计成为友元函数。
-
把‘=’运算符重载为类成员变量,并且将返回值设计成为该类的引用。
-
一定要自定义一个拷贝构造函数,这样在重载运算符返回对象副本的时候,编译器会自动调用拷贝构造函数,否则会出现结果错误。
-
友元关系不会被派生类继承。