【异常机制高级讲解】异常与多态综合案例

简介: 【异常机制高级讲解】异常与多态综合案例

构造函数和析构函数没有返回值,不能像C语言那样用不同的返回值来判断错误的情概况,所以可以通过异常机制来处理错误的情况。

下面给出一个综合案例,该案例包含了异常、多态、类内部包含类、深拷贝、操作符重载、虚函数重写、等综合性知识。(该综合案例将C++的很多语法结合在一起,综合性较强,值得反复练习调试

1. #define _CRT_SECURE_NO_WARNINGS
2. 
3. #include <iostream>
4. using namespace std;
5. 
6. class People
7. {
8. public: //构造析构函数
9.  People(int age, const char* name);
10.   ~People();
11. public: //重载操作符
12.   char& operator[](int index);
13.   friend ostream& operator<<(ostream& out, People& p);
14. public: //提供外部访问私有属性的接口
15.   int get_age();
16. public: //内部类定义异常类型,实现捕获异常的多态行为
17.   class PeopleErrType
18.   {
19.   public:
20.     PeopleErrType(const char* p);
21.     ~PeopleErrType();
22.   public:
23.     virtual void print_err_type() = 0; //People 类中异常的统一接口
24.   protected:
25.     char* err_type_str;
26.   };
27.   class PeopleAgeTooSmall : public PeopleErrType
28.   {
29.   public:
30.     PeopleAgeTooSmall(const char* p) : PeopleErrType(p) {}; //只用于初始化参数列表传给父类
31.   public:
32.     virtual void print_err_type();
33.   };
34.   class PeopleAgeTooBig : public PeopleErrType
35.   {
36.   public:
37.     PeopleAgeTooBig(const char* p) : PeopleErrType(p) {};
38.   public:
39.     virtual void print_err_type();
40.   };
41.   class PeopleNameIsNULL : public PeopleErrType
42.   {
43.   public:
44.     PeopleNameIsNULL(const char* p) : PeopleErrType(p) {};
45.   public:
46.     virtual void print_err_type();
47.   };
48.   class PeopleNameErr : public PeopleErrType
49.   {
50.   public:
51.     PeopleNameErr(const char* p) : PeopleErrType(p) {};
52.   public:
53.     virtual void print_err_type();
54.   };
55. private: //私有属性
56.   int age; //年龄
57.   char* name; //名称
58. };
59. 
60. // People 类的构造函数,会抛出异常
61. People::People(int age, const char* name)
62. {
63.   if (age <= 0)
64.   {
65.     throw PeopleAgeTooSmall("异常:年龄小于0");
66.   }
67.   if (age > 200)
68.   {
69.     throw PeopleAgeTooBig("异常:年龄大于200");
70.   }
71.   if (name == NULL)
72.   {
73.     throw PeopleNameIsNULL("异常:名称为空");
74.   }
75.   if ((name[0] < 'A') || (name[0] > 'Z'))
76.   {
77.     throw PeopleNameErr("异常:名称错误,(name[0] < 'A') || (name[0] > 'Z')");
78.   }
79. 
80.   this->age = age;
81.   this->name = new char[strlen(name) + 1];
82.   strcpy(this->name, name);
83. }
84. 
85. // People 类的析构函数
86. People::~People()
87. {
88.   if (this->name != NULL)
89.   {
90.     delete[] this->name;
91.   }
92.   this->name = NULL;
93.   this->age = 0;
94. }
95. 
96. //外部访问私有属性的接口
97. int People::get_age()
98. {
99.   return this->age;
100. }
101. 
102. //重载 [] 操作符
103. char& People::operator[](int index)
104. {
105.  return this->name[index];
106. }
107. 
108. //重载左移操作符
109. ostream& operator<<(ostream& out, People& p)
110. {
111.  out << "name: " << p.name << " age: " << p.age << endl;
112.  return out;
113. }
114. 
115. //People 类的内部类 构造函数,为输出字符串分配空间
116. People::PeopleErrType::PeopleErrType(const char* p)
117. {
118.  this->err_type_str = new char[strlen(p) + 1];
119.  strcpy(this->err_type_str, p);
120. }
121. 
122. People::PeopleErrType::~PeopleErrType()
123. {
124.  if (this->err_type_str != NULL)
125.  {
126.    delete[] this->err_type_str;
127.  }
128.  this->err_type_str = NULL;
129. }
130. 
131. //异常类型:年龄太小,小于0
132. void People::PeopleAgeTooSmall::print_err_type()
133. {
134.  cout << "err: PeopleAgeTooSmall -> " << err_type_str << endl;
135. }
136. 
137. //异常类型:年龄太大超出范围
138. void People::PeopleAgeTooBig::print_err_type()
139. {
140.  cout << "err: PeopleAgeTooBig -> " << err_type_str << endl;
141. }
142. 
143. //异常类型:名称为空
144. void People::PeopleNameIsNULL::print_err_type()
145. {
146.  cout << "err: PeopleNameIsNULL -> " << err_type_str << endl;
147. }
148. 
149. //异常类型:名称错误
150. void People::PeopleNameErr::print_err_type()
151. {
152.  cout << "err: PeopleNameErr -> " << err_type_str << endl;
153. }
154. 
155. int main()
156. {
157.  try
158.  {
159. //通过以下4个测试例子测试4种异常
160.    //People p(0, "Aily");
161.    //People p(16, NULL);
162.    //People p(300, "Aily");
163.    //People p(16, "aily");
164.    People p(16, "Aily");
165.    cout << "人员信息:" << p << "\t代号:" << p[0] << p.get_age() << endl;
166.  }
167.  catch (People::PeopleErrType & e) //产生多态,自动识别异常类型
168.  {
169.    e.print_err_type();
170.  }
171.  catch (...)
172.  {
173.    cout << "其他未知异常" << endl;
174.  }
175. 
176.  system("pause");
177.  return 0;
178. }

将测试代码依次放开,逐步调试便可以观察到程序的每一步动态

1. //通过以下4个测试例子测试4种异常
2. //People p(0, "Aily");
3. //People p(16, NULL);
4. //People p(300, "Aily");
5. //People p(16, "aily");
6. //People p(16, "Aily");


相关文章
|
存储 Java
map中存储的是引用,而不是对象本身
该内容是关于Java编程中验证Map存储引用而非复制对象的示例。创建大型List导致内存增加,说明List确实占用空间。通过Person类示例,将不同对象放入Map,改变一个对象的属性后,比较原对象与Map中的键值对,发现两者相等,证明Map保存的是对象引用。
252 5
|
SQL 消息中间件 分布式数据库
Flink问题之State 0点清除如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
258 0
|
iOS开发
IOS Pods Failed to connect to www.gstatic.com port 443: Operation timed out
IOS Pods Failed to connect to www.gstatic.com port 443: Operation timed out
247 0
|
11月前
|
SQL 并行计算 数据挖掘
一份写给数据工程师的 Polars 迁移指南:将 Pandas 速度提升 20 倍代码重构实践
Polars作为现代化的数据处理框架,通过先进的工程实践和算法优化,为数据科学工作者提供了高效的数据处理工具。在从Pandas迁移时,理解这些核心概念和最佳实践将有助于充分发挥Polars的性能优势。
707 4
|
数据可视化 算法 Go
【博士每天一篇文献-实验】Exploring the Morphospace of Communication Efficiency in Complex Networks
这篇论文探讨了复杂网络中不同拓扑结构下的通信效率,并使用"效率形态空间"来分析网络拓扑与效率度量之间的关系,得出结论表明通信效率与网络结构紧密相关。
118 3
putchar()函数
【6月更文挑战第24天】putchar()函数。
428 2
|
JSON 关系型数据库 MySQL
这个问题是由于Flink的Table API在处理MySQL数据时,将MULTISET类型的字段转换为了JSON格式
【1月更文挑战第17天】【1月更文挑战第84篇】这个问题是由于Flink的Table API在处理MySQL数据时,将MULTISET类型的字段转换为了JSON格式
249 1
|
机器学习/深度学习 数据采集 编解码
【核磁共振成像】并行采集MRI
【核磁共振成像】并行采集MRI
【核磁共振成像】并行采集MRI
|
人工智能
StyleGAN 调整面部表情,让虚拟人脸更生动
赋予 AI 人脸表情,让其更生动自然
495 3
StyleGAN 调整面部表情,让虚拟人脸更生动
|
存储 SQL 数据库
带你读《2022技术人的百宝黑皮书》——开发规约的意义与细则(5)
带你读《2022技术人的百宝黑皮书》——开发规约的意义与细则(5)
211 0