036:很难蒙混过关的CArray3d三维数组模板类

题目原文

实现一个三维数组模版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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值