第五十八讲 迭代器(3)

关于上一讲我们留下的问题,我们暂且搁在一旁,留给大家去思考我觉得比我现在说出来要好得多,因为现在有更重要的东西要说,从大局观上来说,我们应该要来说说一些关于我们的My_Point,为了让我们下面的代码能够得以运行:
—————————–
1)My_Array<int>*a = new My_Array<int>(10);


2)My_Point<int>p(*a);


3)My_Point<int>p1(*a,5);


——————————

我们现在来分析一下这个类的构造,首先我们要明白一件事,那就是*a并不是int,而是My_Array的对象,不过是经过int具体化后的,而且My_Point居然是指针(我们想要达到内建指针的效果的指针),所以我们的My_Point应该封装一个指向My_Array<T>的指针,并不是指向一个T的指针,说到这里,如果大家对STL熟悉的话应该看出了一些东西出来,当然,我们接下来会说。

我们来看第二句,要让第二句安全的运行起来,我们就应该有一个像下面这样一个构造函数:
—————————–
My_Point(const My_Array<T>&

);


——————————
不过,我们这里还有一个问题,我们并没有表示const My_Array的类,所以我们现在的构造函数还得修改一下,就是去掉const,然后我们再来看看第三句,在第三句里,虽然说我们没有给出原型,但是想必大家一定知道,里面的两个参数应该是My_Array的对象和一个下标,所以我们还得有另一个构造函数,如下:
——————————-
My_Point(My_Array<T>&

t,int n);


——————————-

从这两句话中,我们几乎可以得出,My_Point里面的两个成员数据分别为:
————————–
My_Array<T>* m_Ptr;


unisgned
int m_Size;


————————–

现在我们几乎可以得出一个可以用的My_Point了,他最初的样子就像下面这样:
—————————–
template<typename T>
class My_Point{
public:

My_Point():

m_Ptr(0),m_Size(0)

{ }

My_Point(My_Array<T>&

t):

m_Ptr(&

t)

{

m_Size = t.Size();


}

My_Point(My_Array<T>&

t,int n):

m_Ptr(&

t),m_Size(n)

{ }

T&

operator*() const{

return (*m_Ptr)[m_Size-1];


}

T operator[](int n){

return (*m_Ptr)[n];


}

My_Point(const My_Point&

);


My_Point&

operator=(const My_Point&

);


private:

My_Array<T>* m_Ptr;


unsigned
int m_Size;


};


—————————————-

现在,我们下面的代码就能够运行了:
——————————–
My_Array<int>*a = new My_Array<int>(10);


for(int i=0;

i<10;

i++)

a->insert(i,i);


My_Point<int>p(*a);


*p = 42;


cout<<endl;


cout<<*p<<"

"

<<(*a)[9]<<endl;


My_Point<int>p1(*a,5);


*p1 = 42;


cout<<*p1<<"

"

<<(*a)[4]<<endl;


——————————-

上面的代码有一个问题,大家想想,如果我们的解引用返回的是一个T&

,那么我们可以对*p赋值,但是这样一来,同时也就会运行我们这样的代码通过编译:
——————-
T* t = &

*p;


——————-

这种写法极其怪异,所以,我们当然不希望写出这样的代码出来,如果有人非要这么写,我们给他一个编译错误,所以,我们不能让他返回引用,让他返回T,只是这样一来,我们好像无法更新元素了,不过我们可以使用另一种方式来更新元素,比如说我们添加一个名叫Set的方法:
——————————-

void Set(const T t){

if(m_Ptr)

(*m_Ptr)[m_Size] = t;


}
为了方便,我们再添加一个同名方法:

void Set(int n,const T t){

if(n<0 || n>m_Size)

throw "

over range!!!"

;


(*m_Ptr)[n] = t;


}
———————————-

当然,如果我们使用Set去更新元素的话,那么我们会重新带来一个问题,这个问题留待下一讲吧,现在我们来整理一下我们的My_Point,然后看看他还缺少些什么。
————————————–
template<typename T>
class My_Point{
public:

My_Point():

m_Ptr(0),m_Size(0)

{ }

My_Point(My_Array<T>&

t):

m_Ptr(&

t)

{

m_Size = t.Size();


}

My_Point(My_Array<T>&

t,int n):

m_Ptr(&

t),m_Size(n-1)

{ }


T&

operator*() const{

return (*m_Ptr)[m_Size];


}

T operator[](int n){

return (*m_Ptr)[n];


}

void Set(const T t){

(*m_Ptr)[m_Size] = t;


}

void Set(int n,const T t){

if(n<0 || n>m_Size)

throw "

over range!!!"

;


(*m_Ptr)[n] = t;


}

My_Point(const My_Point&

);


My_Point&

operator=(const My_Point&

);


private:

My_Array<T>* m_Ptr;


unsigned
int m_Size;



};


———————————————

至此,我们要实现的功能完成得差不多了,但是还是有很多问题,就比如我们上面的class里面还有个缺陷,留给大家思考,而且他依然不能让下面的代码顺利执行:
——————————–
My_Array<SpreadSheetCell>* m_Array = new My_Array<SpreadSheetCell>(10);


My_Point<SpreadSheetCell>m_ptr(m_Array,3);


delete m_Array;


m_ptr.Set("

Hello"

);


———————————-

现在看来我们要面对的问题是越来愈多了,大家要思考的也越来越多,哎,想要构架出一个完美的框架还真不是一件容易的事啊。这些问题还是留给大家去思考,我们下周再见。

=================
回复D直接查看目录


原文始发于微信公众号(

C/C++的编程教室

):第五十八讲 迭代器(3)

|

发表评论