构造函数和析构函数没有返回值,不能像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");