继前天凑动态多维数组失败后,经指导,终于将其实现。
把数组的维度一并放在模板里,而不用构造函数来实现,于是定义Array看起来像下边这样,其中NewArray是一个全局变量:
Array<int, 3> a=NewArrary[3][2][1]; //相当于int[3][2][1]
operator[] 是利用特化类模板来实现的:
template<typename _Type, int _DimensionCount>
class Array
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
private:
_Type* Elements;
int Size;
public:
Array<_Type, DimensionCount-1> operator[](const int Index);
};
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template<typename _Type>
class Array<_Type, 1>
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
private:
_Type* Elements;
int Size;
public:
_Type& operator[](const int Index);
_Type operator[](const int Index)const;
};
在实现 Array<_Type, DimensionCount-1> operator[](const int Index) 时遇到一个问题,我需要返回一个Array<_Type, DimensionCount-1>,这个结果是根据当前的Array的信息来生成的,肯定需要用到private成员Elements,于是考虑用friend class Array<_Type, DimensionCount-1>,没想到编译器又喷我了,还是不能通过,原因不明T_T,无奈只能把Elements这些信息放到public下。
Array的测试用例如下:
#include "Library/UnitTest/UnitTest.h"
#include "Library/Basic/Array.h"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
using namespace Lyt;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
void InitArray(int* a, const int Size)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
if (a)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for (int i=0; i<=Size-1; i++) a[i]=i;
}
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
bool CheckArray(int* a1, int* a2, const int Size)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
if (a1 && a2)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for (int i=0; i<=Size-1; i++)
if (a1[i]!=a2[i]) return false;
}
else if (a1 || a2) return false;
return true;
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
TESTCASE(ArrayConstructorAssign, "ArrayConstructor")
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
int a[30];
InitArray(a, 30);
int dims[3];
dims[0]=2;
dims[1]=3;
dims[2]=5;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<int, 3> a1;
EXPECT_TRUE(a1.Dimensions!=0, "DefaultConstructor");
Array<int, 3> a2=NewArray[2][3][5];
InitArray(a2.Elements, a2.Size);
EXPECT_TRUE(CheckArray(dims, a2.Dimensions, 3) && CheckArray(a, a2.Elements, a2.Size), "NewArrayConstructor");
Array<int, 3> a3=a2;
EXPECT_TRUE(CheckArray(dims, a3.Dimensions, 3) && CheckArray(a, a3.Elements, a3.Size), "CopyConstructor");
Array<int, 2> a4=a3[1];
EXPECT_TRUE(CheckArray(dims+1, a4.Dimensions, 2) && CheckArray(a+15, a4.Elements, a4.Size), "CopyConstructor operator[]");
Array<int, 1> a5=a3[1][1];
EXPECT_TRUE(CheckArray(dims+2, a5.Dimensions, 1) && CheckArray(a+20, a5.Elements, a5.Size), "CopyConstructor operator[]");
Array<int, 1> a6=a5;
EXPECT_TRUE(CheckArray(dims+2, a6.Dimensions, 1) && CheckArray(a+20, a6.Elements, a6.Size), "CopyConstructor");
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
EXPECT_TRUE(a2[1][1][0]==20, "operator[]");
EXPECT_TRUE((a2[1][1][0]=30)==30, "operator=");
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
TESTCASE(ArrayAssign, "Array::operator=")
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
int a1[30];
InitArray(a1, 30);
int dims1[3];
dims1[0]=2;
dims1[1]=3;
dims1[2]=5;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int a2[8];
InitArray(a2, 8);
int dims2[3];
dims2[0]=2;
dims2[1]=2;
dims2[2]=2;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<int, 3> Array1=NewArray[2][3][5];
InitArray(Array1.Elements, Array1.Size);
Array<int, 3> Array2=Array1;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<int, 3> Array3=NewArray[2][2][2];
InitArray(Array3.Elements, Array3.Size);
Array1=Array3;
EXPECT_TRUE(CheckArray(dims2, Array1.Dimensions, 3) && CheckArray(a2, Array1.Elements, Array1.Size), "operator=");
EXPECT_TRUE(Array1[0][1][1]==3, "operator[]");
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<int, 2> Array4=Array1[0];
Array<int, 1> Array5=Array1[0][1];
Array5[1]=9;
EXPECT_TRUE(Array1[0][1][1]==9 && Array3[0][1][1]==9 && Array4[1][1]==9, "operator=");
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array3=Array2;
EXPECT_TRUE(CheckArray(dims1, Array3.Dimensions, 3) && CheckArray(a1, Array3.Elements, Array3.Size), "operator=");
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
TESTCASE(ArrayClone, "Array::Clone")
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
int a[30];
InitArray(a, 30);
int dims[3];
dims[0]=2;
dims[1]=3;
dims[2]=5;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<int, 3> a1=NewArray[2][3][5];
InitArray(a1.Elements, a1.Size);
Array<int, 3> a2=a1.Clone();
EXPECT_TRUE(CheckArray(dims, a2.Dimensions, 3) && CheckArray(a, a2.Elements, a2.Size), "Clone");
a1[0][0][0]=100;
EXPECT_TRUE(a1[0][0][0]==100 && a2[0][0][0]==0, "operator=");
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Array源码:
#ifndef ARRAY_H
#define ARRAY_H
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include <memory.h>
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
namespace Lyt
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
template<int _DimensionCount>
class ArrayDimension
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public:
int Data[_DimensionCount+1];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ArrayDimension()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for (int i=0; i<=_DimensionCount-1; i++) Data[i]=0;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ArrayDimension(const int Dimension, int* PrevDimensions)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Data[_DimensionCount-1]=Dimension;
memcpy(Data, PrevDimensions, sizeof(int)*(_DimensionCount-1));
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ArrayDimension<_DimensionCount+1> operator[](const int Dimension)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return ArrayDimension<_DimensionCount+1>(Dimension, Data);
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int GetSize()const
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
int Result=1;
for (int i=0; i<=_DimensionCount-1; i++) Result*=Data[i];
return Result;
}
};
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
extern ArrayDimension<0> NewArray;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template<typename _Type, int _DimensionCount>
class Array
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
protected:
void RefIncrease()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (RefCount) (*RefCount)++;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void RefDecrease()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (RefCount)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (--(*RefCount)==0)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
delete RefCount;
delete[] (Dimensions-DimensionsIndex);
if (Elements) delete[] (Elements-ElementsIndex);
RefCount=0;
Dimensions=0;
Elements=0;
Size=0;
ElementsIndex=0;
DimensionsIndex=0;
}
}
}
public:
int* RefCount;
int* Dimensions;
_Type* Elements;
int Size;
int ElementsIndex;
int DimensionsIndex;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefCount=new int(1);
Dimensions=new int[_DimensionCount];
Elements=0;
Size=0;
ElementsIndex=0;
DimensionsIndex=0;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array(const Array<_Type, _DimensionCount>& Object)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefCount=Object.RefCount;
Dimensions=Object.Dimensions;
Elements=Object.Elements;
Size=Object.Size;
ElementsIndex=Object.ElementsIndex;
DimensionsIndex=Object.DimensionsIndex;
RefIncrease();
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array(const ArrayDimension<_DimensionCount> Dims)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefCount=new int(1);
Dimensions=new int[_DimensionCount];
memcpy(Dimensions, Dims.Data, sizeof(int)*_DimensionCount);
Size=Dims.GetSize();
Elements=new _Type[Size];
ElementsIndex=0;
DimensionsIndex=0;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
~Array()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefDecrease();
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<_Type, _DimensionCount>& operator=(const Array<_Type, _DimensionCount>& Object)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefDecrease();
RefCount=Object.RefCount;
Dimensions=Object.Dimensions;
Elements=Object.Elements;
Size=Object.Size;
ElementsIndex=Object.ElementsIndex;
DimensionsIndex=Object.DimensionsIndex;
RefIncrease();
return *this;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<_Type, _DimensionCount-1> operator[](const int Index)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefIncrease();
Array<_Type, _DimensionCount-1> Result;
delete Result.RefCount;
Result.RefCount=RefCount;
Result.Size=Size/Dimensions[0];
Result.Dimensions=Dimensions+1;
Result.Elements=Elements+Index*Result.Size;
Result.ElementsIndex=ElementsIndex+Index*Result.Size;
Result.DimensionsIndex=DimensionsIndex+1;
return Result;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<_Type, _DimensionCount> Clone()const
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Array<_Type, _DimensionCount> Result;
memcpy(Result.Dimensions, Dimensions, sizeof(int)*(_DimensionCount));
Result.Size=Size;
Result.Elements=new _Type[Size];
memcpy(Result.Elements, Elements, sizeof(int)*(Size));
return Result;
}
};
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template<typename _Type>
class Array<_Type, 1>
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
protected:
void RefIncrease()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (RefCount) (*RefCount)++;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void RefDecrease()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (RefCount)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (--(*RefCount)==0)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
delete RefCount;
delete[] (Dimensions-DimensionsIndex);
if (Elements) delete[] (Elements-ElementsIndex);
RefCount=0;
Dimensions=0;
Elements=0;
Size=0;
ElementsIndex=0;
DimensionsIndex=0;
}
}
}
public:
int* RefCount;
int* Dimensions;
_Type* Elements;
int Size;
int ElementsIndex;
int DimensionsIndex;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefCount=new int(1);
Dimensions=new int[1];
Elements=0;
Size=0;
ElementsIndex=0;
DimensionsIndex=0;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array(const Array<_Type, 1>& Object)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefCount=Object.RefCount;
Dimensions=Object.Dimensions;
Elements=Object.Elements;
Size=Object.Size;
ElementsIndex=Object.ElementsIndex;
DimensionsIndex=Object.DimensionsIndex;
RefIncrease();
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array(const ArrayDimension<1> Dims)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefCount=new int(1);
Dimensions=new int[];
memcpy(Dimensions, Dims.Data, sizeof(int));
Size=Dims.GetSize();
Elements=new _Type[Size];
ElementsIndex=0;
DimensionsIndex=0;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
~Array()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefDecrease();
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<_Type, 1>& operator=(const Array<_Type, 1>& Object)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RefDecrease();
RefCount=Object.RefCount;
Dimensions=Object.Dimensions;
Elements=Object.Elements;
Size=Object.Size;
ElementsIndex=Object.ElementsIndex;
DimensionsIndex=Object.DimensionsIndex;
RefIncrease();
return *this;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
_Type& operator[](const int Index)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (Index<0 || Index>=Dimensions[0]) throw L"越界访问";
else return Elements[Index];
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
_Type operator[](const int Index)const
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (Index<0 || Index>=Dimensions[0]) throw L"越界访问";
else return Elements[Index];
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Array<_Type, 1> Clone()const
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Array<_Type, 1> Result;
mencpy(Result.Dimensions, Dimensions, sizeof(int));
Result.Size=Size;
Result.Elements=new _Type[Size];
memcpy(Result.Elements, Elements, sizeof(int)*(Size));
return Result;
}
};
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#endif
欢迎各位继续喷~
posted on 2009-10-13 14:16
Lyt 阅读(1695)
评论(9) 编辑 收藏 引用 所属分类:
数据结构