题目原文
实现一个三维数组模版CArray3D,可以用来生成元素为任意类型变量的三维数组,输出指定结果
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
template <class T>
class CArray3D
{
// 在此处补充你的代码
};
CArray3D<int> a(3,4,5);
CArray3D<double> b(3,2,2);
void PrintA()
{
for(int i = 0;i < 3; ++i) {
cout << "layer " << i << ":" << endl;
for(int j = 0; j < 4; ++j) {
for(int k = 0; k < 5; ++k)
cout << a[i][j][k] << "," ;
cout << endl;
}
}
}
void PrintB()
{
for(int i = 0;i < 3; ++i) {
cout << "layer " << i << ":" << endl;
for(int j = 0; j < 2; ++j) {
for(int k = 0; k < 2; ++k)
cout << b[i][j][k] << "," ;
cout << endl;
}
}
}
int main()
{
int No = 0;
for( int i = 0; i < 3; ++ i ) {
a[i];
for( int j = 0; j < 4; ++j ) {
a[j][i];
for( int k = 0; k < 5; ++k )
a[i][j][k] = No ++;
a[j][i][i];
}
}
PrintA();
memset(a[1],-1 ,20*sizeof(int));
memset(a[1],-1 ,20*sizeof(int));
PrintA();
memset(a[1][1],0 ,5*sizeof(int));
PrintA();
for( int i = 0; i < 3; ++ i )
for( int j = 0; j < 2; ++j )
for( int k = 0; k < 2; ++k )
b[i][j][k] = 10.0/(i+j+k+1);
PrintB();
int n = a[0][1][2];
double f = b[0][1][1];
cout << "****" << endl;
cout << n << "," << f << endl;
return 0;
}
样例输出
layer 0:
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
layer 1:
20,21,22,23,24,
25,26,27,28,29,
30,31,32,33,34,
35,36,37,38,39,
layer 2:
40,41,42,43,44,
45,46,47,48,49,
50,51,52,53,54,
55,56,57,58,59,
layer 0:
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
layer 1:
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
layer 2:
40,41,42,43,44,
45,46,47,48,49,
50,51,52,53,54,
55,56,57,58,59,
layer 0:
0,1,2,3,4,
5,6,7,8,9,
10,11,12,13,14,
15,16,17,18,19,
layer 1:
-1,-1,-1,-1,-1,
0,0,0,0,0,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,
layer 2:
40,41,42,43,44,
45,46,47,48,49,
50,51,52,53,54,
55,56,57,58,59,
layer 0:
10,5,
5,3.33333,
layer 1:
5,3.33333,
3.33333,2.5,
layer 2:
3.33333,2.5,
2.5,2,
****
7,3.33333
提示
建议做法:
a[i][j][k] 这个表达式的第一个[]返回一个内部类的对象,该内部类也重载了[],且返回值为指针。
必要时需重载对象到指针的强制类型转换运算符
分析
我一开始想的是,构造一个2D数组类作为3D数组[]运算符的结果,但是毕竟只能改类内部的代码,因此按照建议做法来做。
首先来一个constructor和destructor,初始化3D数组的尺寸
CArray3D(int l,int r,int c):layer(l), row(r), col(c)
{
p = new T[l * r * c];
}
virtual ~CArray3D()
{
delete[] p;
}
接着我们使用[]运算符的时候,需要返回一个中间结果2D数组,这个中间结果也必须重载运算符[]。考虑用指针,行,列,去初始化这个数组,这里面指针的偏移可以自己计算一下。
CArray2D<T> operator[](int layer)
{
return CArray2D<T>(p + layer * row * col, row, col);
}
对应的构造函数如下,注意的是,这里无须申请空间,因为我们希望改2D数组中的数据,原来3D数组的数据也能修改
CArray2D(T* p, int r, int c) : p(p), row(r), col(c)
{
}
补充完整这个内部类,重载[],返回一个指针,代表一维数组。
这里的注意点是,不要析构!这是原来3D数组的一部分。
template <class T>
class CArray2D
{
private:
int row;
int col;
T* p;
public:
CArray2D(T* p, int r, int c) : p(p), row(r), col(c)
{
}
virtual ~CArray2D()
{
//一定不要析构!!!
}
T* operator[](int row)
{
return p + row * col;
}
};
此时尝试运行,发现报了一个错误。大概意思是说,没有从3D数组到void *的转换函数。
读代码发现,main函数中有一个:
memset(a[1], -1, 20 * sizeof(int));
a[1]是个二维数组,因此需要写一个「类型转换运算符重载」。
给内部类CArray2D加上,使得它和「指向内部数据的指针」可以转换。
operator void* ()
{
return p;
}
最后代码如下https://github.com/lagrange10/learnCPP/blob/master/%E4%BD%9C%E4%B8%9A3%E2%80%94%E2%80%94%E5%BE%88%E9%9A%BE%E8%92%99%E6%B7%B7%E8%BF%87%E5%85%B3%E7%9A%843Darray/%E6%BA%90.cpp
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
template <class T>
class CArray3D
{
// 在此处补充你的代码
private:
int layer;
int row;
int col;
T* p;
public:
// ---------------------内部类CArray2D-----------------------
//这个内部类是用来表达CArray3D的每一层的内容的,因此T* p所指的内容是CArray3D中的东西
template <class T>
class CArray2D
{
private:
int row;
int col;
T* p;
public:
CArray2D(T* p, int r, int c) : p(p), row(r), col(c)
{
}
virtual ~CArray2D()
{
//一定不要析构!!!
}
T* operator[](int row)
{
return p + row * col;
}
friend class CArray3D;
operator void* ()
{
return p;
}
};
// ---------------------内部类CArray2D结束------------------
CArray3D(int l,int r,int c):layer(l), row(r), col(c)
{
p = new T[l * r * c];
}
virtual ~CArray3D()
{
delete[] p;
}
CArray2D<T> operator[](int layer)
{
return CArray2D<T>(p + layer * row * col, row, col);
}
};
CArray3D<int> a(3, 4, 5);
CArray3D<double> b(3, 2, 2);
void PrintA()
{
for (int i = 0; i < 3; ++i) {
cout << "layer " << i << ":" << endl;
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 5; ++k)
cout << a[i][j][k] << ",";
cout << endl;
}
}
}
void PrintB()
{
for (int i = 0; i < 3; ++i) {
cout << "layer " << i << ":" << endl;
for (int j = 0; j < 2; ++j) {
for (int k = 0; k < 2; ++k)
cout << b[i][j][k] << ",";
cout << endl;
}
}
}
int main()
{
int No = 0;
for (int i = 0; i < 3; ++i) {
a[i];
for (int j = 0; j < 4; ++j) {
a[j][i];
for (int k = 0; k < 5; ++k)
a[i][j][k] = No++;
a[j][i][i];
}
}
PrintA();
memset(a[1], -1, 20 * sizeof(int));
memset(a[1], -1, 20 * sizeof(int));
PrintA();
memset(a[1][1], 0, 5 * sizeof(int));
PrintA();
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 2; ++j)
for (int k = 0; k < 2; ++k)
b[i][j][k] = 10.0 / (i + j + k + 1);
PrintB();
int n = a[0][1][2];
double f = b[0][1][1];
cout << "****" << endl;
cout << n << "," << f << endl;
return 0;
}