创建数据结构库基础设施——异常类的构建

1,数据结构库架构图(本文暂时架构图,后有更改):

 

2,依赖异常类创建的库稳定性很好;

3,异常类型可以是自定义类类型:

       1,对于类类型异常的匹配依旧是至上而下严格匹配;

       2,赋值兼容性原则在异常匹配中依然适用;

       3,一般而言:

              1,匹配子类异常的 catch 放在上部;

              2,匹配父类异常的 catch 放在下部;

             

4,纯虚的析构函数仅仅用来说明当前的类是抽象类,其它没有任何说明了;

5,纯虚析构函数的实现:

       1,C++ 中规定纯虚函数不需要提供实现,等着子类实现;

       2,C++ 中规定,只要定义了析构函数,不管其是否为纯虚函数,一定要提供实现,因为在实现一个析构函数的时候,最后肯定要调用父类的析构函数,如果父类的析构函数是纯虚函数,并且这个纯虚函数没有具体实现,则调用到顶层父类的析构函数时没有实现,则更加奇怪,所以 C++ 语言规定了这个原则;

6,现代 C++ 库必然包含必要的异常类族,异常类是数据结构类所依赖的“基础设施”,其成员关系为:

 

 

7,异常类功能定义:

 

 

8,异常类中的接口定义:

 

 

9,异常类族创建:

1,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 void init(const char* message, const char* file, int line);
 17 
 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     Exception(const Exception& e);
 23 Exception& operator= (const Exception& e);
 24 
 25     virtual const char* message() const;    // 详细的异常说明信息;
 26     virtual const char* location() const;   // 定位异常位置信息;
 27     virtual ~Exception() = 0;   //抽象类,析构函数用虚函数;纯虚函数的实现等着子类来完成;但凡定义析构函数,必须实现,因为析构函数时,必须要调用父类的析构函数。
 28 };
 29 
 30 class ArithmeticException : public Exception
 31 {
 32 public:
 33     ArithmeticException() : Exception(0){}
 34     ArithmeticException(const char* message) : Exception(message){}
 35     ArithmeticException(const char *file, int line) : Exception(file, line){}
 36     ArithmeticException(const char* message, const char* file, int line) : Exception(message, file, line){}
 37     ArithmeticException(const ArithmeticException& e) : Exception(e) {}
 38     ArithmeticException& operator =(const ArithmeticException& e)
 39     {
 40         Exception::operator =(e);
 41 
 42         return *this;
 43     }
 44 };
 45 
 46 class NullPointerException : public Exception
 47 {
 48 public:
 49     NullPointerException() : Exception(0){}
 50     NullPointerException(const char* message) : Exception(message){}
 51     NullPointerException(const char *file, int line) : Exception(file, line){}
 52     NullPointerException(const char* message, const char* file, int line) : Exception(message, file, line){}
 53     NullPointerException(const NullPointerException& e) : Exception(e) {}
 54     NullPointerException& operator =(const NullPointerException& e)
 55     {
 56         Exception::operator =(e);
 57 
 58         return *this;
 59     }
 60 };
 61 
 62 class IndexOutOfBoundsException : public Exception
 63 {
 64 public:
 65     IndexOutOfBoundsException() : Exception(0){}
 66     IndexOutOfBoundsException(const char* message) : Exception(message){}
 67     IndexOutOfBoundsException(const char *file, int line) : Exception(file, line){}
 68     IndexOutOfBoundsException(const char* message, const char* file, int line) : Exception(message, file, line){}
 69     IndexOutOfBoundsException(const IndexOutOfBoundsException& e) : Exception(e) {}
 70     IndexOutOfBoundsException& operator =(const IndexOutOfBoundsException& e)
 71     {
 72         Exception::operator =(e);
 73 
 74         return *this;
 75     }
 76 };
 77 
 78 class NoEnoughMemoryException : public Exception
 79 {
 80 public:
 81     NoEnoughMemoryException() : Exception(0){}
 82     NoEnoughMemoryException(const char* message) : Exception(message){}
 83     NoEnoughMemoryException(const char *file, int line) : Exception(file, line){}
 84     NoEnoughMemoryException(const char* message, const char* file, int line) : Exception(message, file, line){}
 85     NoEnoughMemoryException(const NoEnoughMemoryException& e) : Exception(e) {}
 86     NoEnoughMemoryException& operator =(const NoEnoughMemoryException& e)
 87     {
 88         Exception::operator =(e);
 89 
 90         return *this;
 91     }
 92 };
 93 
 94 class InvalidParameterException : public Exception
 95 {
 96 public:
 97     InvalidParameterException() : Exception(0){}
 98     InvalidParameterException(const char* message) : Exception(message){}
 99     InvalidParameterException(const char *file, int line) : Exception(file, line){}
100     InvalidParameterException(const char* message, const char* file, int line) : Exception(message, file, line){}
101     InvalidParameterException(const InvalidParameterException& e) : Exception(e) {}
102     InvalidParameterException& operator =(const InvalidParameterException& e)
103     {
104         Exception::operator =(e);
105 
106         return *this;
107     }
108 };
109 
110 class InvalidOperationException : public Exception
111 {
112 public:
113     InvalidOperationException() : Exception(0){}
114     InvalidOperationException(const char* message) : Exception(message){}
115     InvalidOperationException(const char *file, int line) : Exception(file, line){}
116     InvalidOperationException(const char* message, const char* file, int line) : Exception(message, file, line){}
117     InvalidOperationException(const InvalidOperationException& e) : Exception(e) {}
118     InvalidOperationException& operator =(const InvalidOperationException& e)
119     {
120         Exception::operator =(e);
121 
122         return *this;
123     }
124 };
125 
126 }
127 
128 #endif // EXCEPTION_H

2,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 = (message ? strdup(message) : NULL);  // 将message复制一份指向堆空间,而内容相同;保证是独立的堆空间;采用三目运算符因为 message 可能为空但是 strdup 没有判断为空的情况;
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 )  // 对于 DTLib 里面的类的话,动态申请后一定要判断是否为空指针,这里不再做为空的异常处理,免得陷入死循环
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;  // 这里已经做了 m_location 为空的准备;
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_location = 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 }

10,设计原则:

       1,在可复用代码库设计时,尽量使用面相对象技术进行架构;

       2,尽量使用异常处理机制分离正常逻辑和异常逻辑;

11,小结:

  1,现代 C++ 库必然包含必要的异常类族;

  2,所有库中的数据结构都依赖于异常机制;

  3,异常机制能够分离库中代码的正常逻辑和异常逻辑;

猜你喜欢

转载自www.cnblogs.com/dishengAndziyu/p/10920566.html