第十九课 数组类的创建(上)


基于顺序存储结构的线性表可能被当成数组来误用,这一节我们要设计数组类来代替原生数组。

课程目标:

Array是一个抽象类,这个类存在的意义就是用来被继承。

需求分析:

原生数组是不提供复制操作的,我们自己的数组要提供复制操作。

length()成员函数设置为纯虚函数,说明这个类是一个纯虚类,用于被继承,具体实现在子类中完成。

在工程中添加Array.h文件:

 1 #ifndef ARRAY_H
 2 #define ARRAY_H
 3 
 4 #include "Object.h"
 5 #include "Exception.h"
 6 
 7 namespace DTLib
 8 {
 9 
10 template <typename T>
11 class Array : public Object
12 {
13 protected:
14     T* m_array;
15 public:
16     virtual bool set(int i, const T&e)    //O(1)
17     {
18         bool ret = ((0 <= i) && (i < length()));
19 
20         if( ret )
21         {
22             m_array[i] = e;
23         }
24     }
25 
26     virtual bool get(int i, T& e) const  //O(1)
27     {
28         bool ret = ((0 <= i) && (i < length()));
29 
30         if( ret )
31         {
32             e = m_array[i];
33         }
34     }
35 
36     T& operator[] (int i)   //O(1)
37     {
38         if((0 <= i) && (i < length()))
39         {
40             return m_array[i];
41         }
42         else
43         {
44             THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
45         }
46     }
47 
48     T operator[] (int i) const   //O(1)
49     {
50         return (const_cast<Array<T>>(*this))[i];
51     }
52 
53     virtual int length() const = 0;
54 };
55 
56 }
57 
58 #endif // ARRAY_H

StaticArray设计:

添加StaticArray.h文件,如下:

 1 #ifndef STATICARRAY_H
 2 #define STATICARRAY_H
 3 
 4 #include "Array.h"
 5 
 6 namespace DTLib
 7 {
 8 
 9 template <typename T, int N>
10 class StaticArray : public Array<T>
11 {
12 protected:
13     T m_space[N];
14 public:
15     StaticArray()   //O(1)
16     {
17         this->m_array = m_space;   //将定义的原生数组挂接到指针上去
18     }
19 
20     StaticArray(const StaticArray<T, N>& obj)  //O(n)
21     {
22         this->m_array = m_space;
23 
24         for(int i = 0; i < N; i++)
25         {
26             m_space[i] = obj.m_space[i];
27         }
28     }
29 
30     StaticArray<T, N>& operator= (const StaticArray<T, N>& obj)  //O(n)
31     {
32         if( this != &obj )
33         {
34             for(int i = 0; i < N; i++)
35             {
36                 m_space[i] = obj.m_space[i];
37             }
38         }
39 
40         return *this;
41     }
42 
43     int length() const   // O(1)
44     {
45         return N;
46     }
47 };
48 
49 }
50 
51 #endif // STATICARRAY_H

测试程序如下:

 1 #include <iostream>
 2 #include "StaticArray.h"
 3 
 4 
 5 using namespace std;
 6 using namespace DTLib;
 7 
 8 
 9 int main()
10 {
11 
12     StaticArray<int, 5> s1;
13 
14     for(int i = 0; i<s1.length(); i++)
15     {
16         s1[i] = i * i;
17     }
18 
19     for(int i = 0; i < s1.length(); i++)
20     {
21         cout << s1[i] << endl;
22     }
23 
24     return 0;
25 }

运行结果如下:

第16、21行可以使用数组下标访问了,打印结果也是正确的。

第二个测试程序:

 1 #include <iostream>
 2 #include "StaticArray.h"
 3 
 4 
 5 using namespace std;
 6 using namespace DTLib;
 7 
 8 
 9 int main()
10 {
11 
12     StaticArray<int, 5> s1;
13 
14     for(int i = 0; i<s1.length(); i++)
15     {
16         s1[i] = i * i;
17     }
18 
19     for(int i = 0; i < s1.length(); i++)
20     {
21         cout << s1[i] << endl;
22     }
23 
24     StaticArray<int, 5> s2;
25 
26     s2 = s1;
27 
28     for(int i = 0; i < s2.length(); i++)
29     {
30         cout << s2[i] << endl;
31     }
32 
33     return 0;
34 }

结果如下:

可以看到第26行数组之间的赋值完全是合法的。

修改测试程序:

 1 #include <iostream>
 2 #include "StaticArray.h"
 3 
 4 
 5 using namespace std;
 6 using namespace DTLib;
 7 
 8 
 9 int main()
10 {
11 
12     StaticArray<int, 5> s1;
13 
14     for(int i = 0; i<s1.length(); i++)
15     {
16         s1[i] = i * i;
17     }
18 
19     for(int i = 0; i < s1.length(); i++)
20     {
21         cout << s1[i] << endl;
22     }
23 
24     StaticArray<int, 5> s2;
25 
26     s2 = s1;
27 
28     for(int i = 0; i < s2.length(); i++)
29     {
30         cout << s2[i] << endl;
31     }
32 
33     s2[6] = 100;
34 
35     return 0;
36 }

结果如下:

可以看到33行的越界赋值引发了异常,这样做的好处是在有bug的地方立即抛出异常,而不是等到程序运行了很长时间才出现bug,那时候定位bug是很困难的。

抛出异常这种方式不会引起bug的传播。有问题的地方就立即反应出来。

原生数组是做不到这一点的。

优质内容筛选与推荐>>
1、浅析JavaScript中this储存
2、2014小结
3、通俗易懂的Java序列化原理
4、Sublime Text 3 编辑器使用
5、The ServiceClass object does not implement the required method in the following form: OMElement sayHello(OMElement e)


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn