前几节我们开发的智能指针类和异常类族并没有继承自Object,现在我们需要将它们进行整合,作为DTLib这个类库的基础设施。整合的时候需要遵循现代软件的架构模式。

  遵循经典设计准则

    DTLib中所有类位于单一继承树,可以根据下图中的方式进行整合:

  在异常类族中有了新的成员InvalidOperationException异常类。为什么要增加这个异常类呢?因为我们创建的数据结构类是有状态的,在不同状态下,成员函数调用的行为是不同的。特别的在某些类对象的初识状态下,某些成员函数是不能调用的,如果硬是要调用这些函数,就会抛出这个非法操作的异常。

改进的关键点:

  Exception类继承自Object类

    堆空间中创建异常对象失败时,返回NULL指针

  新增InvalidOperationException异常类

    成员函数调用时,如果状态不正确则抛出异常

  SmartPointer类继承自Object类

    堆空间中创建智能指针对象失败时,返回NULL指针

DTLib中类的使用原则:

  如果在堆空间中创建DTLib库中的对象,创建完之后要判断一下是否返回了一个合法的指针。因为创建失败时是不会返回异常的。

改造后的程序库如下:

Exception.h

  1 #ifndef EXCEPTION_H
  2 #define EXCEPTION_H
  3
  4 #include "Object.h"
  5
  6 namespace DTLib
  7 {
  8
  9 #define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))
 10
 11 class Exception : public Object
 12 {
 13 protected:
 14     char *m_message;
 15     char *m_location;
 16
 17     void init(const char* message, const char* file, int line);
 18 public:
 19     Exception(const char* message);
 20     Exception(const char* file, int line);
 21     Exception(const char* message, const char* file, int line);
 22
 23     Exception(const Exception& e);
 24     Exception& operator= (const Exception& e);
 25
 26     virtual const char* message() const;
 27     virtual const char* location() const;
 28
 29     virtual ~Exception() = 0;
 30 };
 31
 32 class ArithmeticException : public Exception
 33 {
 34 public:
 35     ArithmeticException() : Exception(0, 0, 0) {}
 36     ArithmeticException(const char* message) : Exception(message) {}
 37     ArithmeticException(const char* file, int line) : Exception(file, line) {}
 38     ArithmeticException(const char* message, const char* file, int line) : Exception(message, file, line){}
 39
 40     ArithmeticException(const ArithmeticException& e) : Exception(e) {}
 41
 42     ArithmeticException& operator=(const ArithmeticException& e)
 43     {
 44         Exception::operator =(e);
 45
 46         return *this;
 47     }
 48 };
 49
 50 class NullPointerException : public Exception
 51 {
 52 public:
 53     NullPointerException() : Exception(0, 0, 0) {}
 54     NullPointerException(const char* message) : Exception(message) {}
 55     NullPointerException(const char* file, int line) : Exception(file, line) {}
 56     NullPointerException(const char* message, const char* file, int line) : Exception(message, file, line){}
 57
 58     NullPointerException(const NullPointerException& e) : Exception(e) {}
 59
 60     NullPointerException& operator=(const NullPointerException& e)
 61     {
 62         Exception::operator =(e);
 63
 64         return *this;
 65     }
 66 };
 67
 68 class IndexOutOfBoundsException : public Exception
 69 {
 70 public:
 71     IndexOutOfBoundsException() : Exception(0, 0, 0) {}
 72     IndexOutOfBoundsException(const char* message) : Exception(message) {}
 73     IndexOutOfBoundsException(const char* file, int line) : Exception(file, line) {}
 74     IndexOutOfBoundsException(const char* message, const char* file, int line) : Exception(message, file, line){}
 75
 76     IndexOutOfBoundsException(const IndexOutOfBoundsException& e) : Exception(e) {}
 77
 78     IndexOutOfBoundsException& operator=(const IndexOutOfBoundsException& e)
 79     {
 80         Exception::operator =(e);
 81
 82         return *this;
 83     }
 84 };
 85
 86 class NoEnoughMemoryException : public Exception
 87 {
 88 public:
 89     NoEnoughMemoryException() : Exception(0, 0, 0) {}
 90     NoEnoughMemoryException(const char* message) : Exception(message) {}
 91     NoEnoughMemoryException(const char* file, int line) : Exception(file, line) {}
 92     NoEnoughMemoryException(const char* message, const char* file, int line) : Exception(message, file, line){}
 93
 94     NoEnoughMemoryException(const NoEnoughMemoryException& e) : Exception(e) {}
 95
 96     NoEnoughMemoryException& operator=(const NoEnoughMemoryException& e)
 97     {
 98         Exception::operator =(e);
 99
100         return *this;
101     }
102 };
103
104 class InvalidParameterException : public Exception
105 {
106 public:
107     InvalidParameterException() : Exception(0, 0, 0) {}
108     InvalidParameterException(const char* message) : Exception(message) {}
109     InvalidParameterException(const char* file, int line) : Exception(file, line) {}
110     InvalidParameterException(const char* message, const char* file, int line) : Exception(message, file, line){}
111
112     InvalidParameterException(const InvalidParameterException& e) : Exception(e) {}
113
114     InvalidParameterException& operator=(const InvalidParameterException& e)
115     {
116         Exception::operator =(e);
117
118         return *this;
119     }
120 };
121
122 class InvalidOperationException : public Exception
123 {
124 public:
125     InvalidOperationException() : Exception(0, 0, 0) {}
126     InvalidOperationException(const char* message) : Exception(message) {}
127     InvalidOperationException(const char* file, int line) : Exception(file, line) {}
128     InvalidOperationException(const char* message, const char* file, int line) : Exception(message, file, line){}
129
130     InvalidOperationException(const InvalidOperationException& e) : Exception(e) {}
131
132     InvalidOperationException& operator=(const InvalidOperationException& e)
133     {
134         Exception::operator =(e);
135
136         return *this;
137     }
138 };
139
140 }
141
142 #endif // EXCEPTION_H

Exception.cpp也进行改造,如下:

 1 #include "Exception.h"
 2 #include <cstring>
 3 #include <cstdlib>
 4
 5 using namespace std;
 6
 7 namespace DTLib
 8 {
 9
10 void Exception::init(const char *message, const char *file, int line)
11 {
12     m_message = strdup(message);
13
14     if(file != NULL)
15     {
16         char sl[16] = {0};
17
18         itoa(line, sl, 10);
19
20         m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
21
22         if(m_location != NULL)
23         {
24             m_location = strcpy(m_location, file);
25             m_location = strcat(m_location, ":");
26             m_location = strcat(m_location, sl);
27         }
28     }
29     else
30     {
31         m_location = NULL;
32     }
33 }
34
35 Exception::Exception(const char *message)
36 {
37     init(message, NULL, 0);
38 }
39
40 Exception::Exception(const char *file, int line)
41 {
42     init(NULL, file, line);
43 }
44
45 Exception::Exception(const char *message, const char *file, int line)
46 {
47     init(message, file, line);
48 }
49
50 Exception::Exception(const Exception &e)
51 {
52     m_message = strdup(e.m_message);
53     m_location = strdup(e.m_location);
54 }
55
56 Exception& Exception::operator =(const Exception& e)
57 {
58     if(this != &e)
59     {
60         free(m_message);
61         free(m_location);
62
63         m_message = strdup(e.m_message);
64         m_message = strdup(e.m_location);
65     }
66
67     return *this;
68 }
69
70 const char* Exception::message() const
71 {
72     return m_message;
73 }
74
75 const char* Exception::location() const
76 {
77     return m_location;
78 }
79
80 Exception::~Exception()
81 {
82     free(m_message);
83     free(m_location);
84 }
85
86 }

第22行的init函数中我们加入了空指针的判断,当malloc申请不成功时,也即m_location为空时,我们什么也不做,就让m_location为空。如果m_location为空,我们抛出异常,会造成死循环,因为在init函数中,我们的Exception对象还没有构造好呢。

SmartPointer.h

 1 #ifndef SMARTPOINTER_H
 2 #define SMARTPOINTER_H
 3
 4 #include "Object.h"
 5
 6 namespace DTLib
 7 {
 8
 9 template <typename T>
10 class SmartPointer : public Object
11 {
12 protected:
13     T *m_pointer;
14
15 public:
16     SmartPointer(T *p = NULL)
17     {
18         m_pointer = p;
19     }
20
21     SmartPointer(const SmartPointer<T>& obj)
22     {
23         m_pointer = obj.m_pointer;
24
25         const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
26     }
27
28     SmartPointer<T>& operator= (const SmartPointer<T>& obj)
29     {
30         if(this != &obj)
31         {
32             delete m_pointer;
33
34             m_pointer = obj.m_pointer;
35
36             const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
37         }
38
39         return *this;
40     }
41
42     T* operator-> ()
43     {
44         return m_pointer;
45     }
46
47     T& operator* ()
48     {
49         return *m_pointer;
50     }
51
52     bool isNull()
53     {
54         return (m_pointer == NULL);
55     }
56
57     T* get()
58     {
59         return m_pointer;
60     }
61
62     ~SmartPointer()
63     {
64         delete m_pointer;
65     }
66 };
67
68 }
69
70 #endif // SMARTPOINTER_H

main函数测试程序如下:

 1 #include <iostream>
 2 #include "Exception.h"
 3 #include "Object.h"
 4 #include "SmartPointer.h"
 5 using namespace std;
 6 using namespace DTLib;
 7
 8
 9
10 int main()
11 {
12     SmartPointer<int> *sp = new SmartPointer<int>();
13
14     delete sp;
15
16     return 0;
17 }

我们在Exception.cpp中new和delete重载的地方打上断点,执行程序结果如下:

可以看到,程序最终执行到了我们自己定义的new和delete处。

DTLib的开发方式和注意事项:

迭代开发:

  每次完成一个小的目标,持续开发,最终打造一个可复用类库

单一继承树:

  所有类都继承自Object,规范堆对象创建时的行为

只抛异常,不处理异常:

  使用THROW_EXCEPTION抛出异常,提高可移植性,有些老的编译器不支持异常,不支持try...catch...,或者有的公司规定不能使用异常机制,这时,如果还想使用

  这个库,我们只需将这个宏定义为空

弱耦合性:

  尽量不使用标准库中的类和函数,提高可移植性

第一阶段的总结:

  数据结构与算法之间的关系

  算法效率的度量方法

  DTLib的基础设施构建

    顶层父类

    智能指针

    异常类

转载于:https://www.cnblogs.com/wanmeishenghuo/p/9500889.html

第十三课 类族结构的进化相关推荐

  1. C++数据结构第13课、类族结构的进化

    遵循经典设计准则 改进的关键点 - Exception 类继承自 Object 类 堆空间中创建异常对象失败后,返回NULL指针 - 新增 InvalidOperationException 异常类 ...

  2. C#之windows桌面软件第十三课:C#中常用的类有哪些?构造函数怎么用?

    C#之windows桌面软件第十三课:C#中常用的类有哪些?构造函数怎么用? using System; using System.Collections.Generic; using System. ...

  3. Vue2+Vue3的专题目录结构(第二十三课)

    这个世界有些事情真的是无法改变的,我们唯一能做的,只是在自己与世界之间找到一个平衡点. 了解Vue框架的大致学习方向(第一课)_星辰镜的博客-CSDN博客 Vue框架的学习(Vue的基础指令操作一)第 ...

  4. NeHe OpenGL第三十三课:TGA文件

    NeHe OpenGL第三十三课:TGA文件 加载压缩和未压缩的TGA文件: 在这一课里,你将学会如何加载压缩和为压缩的TGA文件,由于它使用RLE压缩,所以非常的简单,你能很快地熟悉它的.   我见 ...

  5. 列表怎么有限的初始化为零_《零基础学习Android开发》第五课 类与面向对象编程1-1...

    视频:<零基础学习Android开发>第五课 类与面向对象编程1-1 类的定义.成员变量.构造方法.成员方法 一.从数据与逻辑相互关系审视代码 通过前面的课程,我们不断接触Java语言的知 ...

  6. OpenGL教程翻译 第二十三课 阴影贴图(一)

    第二十三课 阴影贴图(一) 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) 背景 阴影和光是紧密联系在一起的,因为如果你想要产生一个阴影就必须要光.有许多的 ...

  7. 《SQL必知必会》第十三课 创建高级联结表 使用不同类型的联结 使用带聚集函数的联结 使用联结时应注意的问题

    第十三课 创建高级联结表 #使用表别名的原因 #不同的联结类型以及每类联结所使用的语法 #如何与联结一起使用聚集函数 #使用联结时的注意问题 一.使用表别名 [1]前面(第七课)介绍使用别名引用被检索 ...

  8. Java第五课. 类对象

    Java第五课. 类&对象 回顾 1. 冒泡:概念,实现:2个for循环分别起的作用 2. 二维数组可以理解成表格:有行有列,行当成一维数组,列当成一维数组中的元素,行有下标(几个一维数组), ...

  9. 手把手教你读财报---银行业---第十三课

    第十三课 利润表(上) 其他综合收益 所谓其他综合收益,就是那些影响本期净资产,但不影响本期净利润的各项利得和损失扣除所得税后的净额.这部分以前是计入"资本公积---其他资本公积" ...

最新文章

  1. vue 入门notes
  2. c语言md5函数 linux,Linux下C语言计算文件的md5值(长度32)
  3. 技术管理角色认知-管理都需要做哪些事
  4. 创建数据库链接(dblink)步骤
  5. 基于jquery的异步提交例子
  6. Acad::ErrorStatus
  7. 【语音处理】基于matlab GUI音乐多次回声图谱显示【含Matlab源码 1733期】
  8. Matlab2014的下载和安装激活过程
  9. 三极管开关电路_简析三极管开关电路设计
  10. 反应釜cad图_反应罐系列图(5张图)CAD格式
  11. 本地搭建电影网站:安装部署MacCMS10 2/3
  12. 胶原蛋白市场爆发,德国vikki如何在市场异军突起?
  13. python3调用cpp的方法——python调用so
  14. 使用Hexo 在本地搭建博客(一)
  15. Ubuntu下载与安装
  16. Birt报表开发工具及Birt runtime部署
  17. 专家揭示连锁加盟陷阱
  18. 小程序源码:修复登录接口版最新知识付费变现小程序源码下载-独立后台版本
  19. Excel导入,一般会遇到的一些问题
  20. 欧拉函数|(扩展)欧拉定理|欧拉反演

热门文章

  1. android动态扩容数组,ArrayList 扩容 Android Java 真的不一样
  2. 使用ctex宏包出现的kpathsea错误
  3. 【ML从入门到入土系列01】概述
  4. 跑步机健身器材标准ENISO20957检测范围有哪些
  5. 数据分析-spss4.30
  6. Oracle数据库的一点
  7. 易优EyouCMS手机端url路径改为/mobile/方案(非自带m.xxx.com二级域名方案)
  8. android pcm文件大小_Android中的PCM设备
  9. 禅与摩托车维修艺术(4)
  10. 硬件使用74hc138的C语言程序,单片机74HC138三八译码器的原理及应用方法