【异常机制高级讲解】异常与多态综合案例
构造函数和析构函数没有返回值,不能像C语言那样用不同的返回值来判断错误的情概况,所以可以通过异常机制来处理错误的情况。
下面给出一个综合案例,该案例包含了异常、多态、类内部包含类、深拷贝、操作符重载、虚函数重写、等综合性知识。(该综合案例将C++的很多语法结合在一起,综合性较强,值得反复练习调试)
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class People
{
public: //构造析构函数
People(int age, const char* name);
~People();
public: //重载操作符
char& operator[](int index);
friend ostream& operator<<(ostream& out, People& p);
public: //提供外部访问私有属性的接口
int get_age();
public: //内部类定义异常类型,实现捕获异常的多态行为
class PeopleErrType
{
public:
PeopleErrType(const char* p);
~PeopleErrType();
public:
virtual void print_err_type() = 0; //People 类中异常的统一接口
protected:
char* err_type_str;
};
class PeopleAgeTooSmall : public PeopleErrType
{
public:
PeopleAgeTooSmall(const char* p) : PeopleErrType(p) {}; //只用于初始化参数列表传给父类
public:
virtual void print_err_type();
};
class PeopleAgeTooBig : public PeopleErrType
{
public:
PeopleAgeTooBig(const char* p) : PeopleErrType(p) {};
public:
virtual void print_err_type();
};
class PeopleNameIsNULL : public PeopleErrType
{
public:
PeopleNameIsNULL(const char* p) : PeopleErrType(p) {};
public:
virtual void print_err_type();
};
class PeopleNameErr : public PeopleErrType
{
public:
PeopleNameErr(const char* p) : PeopleErrType(p) {};
public:
virtual void print_err_type();
};
private: //私有属性
int age; //年龄
char* name; //名称
};
// People 类的构造函数,会抛出异常
People::People(int age, const char* name)
{
if (age <= 0)
{
throw PeopleAgeTooSmall("异常:年龄小于0");
}
if (age > 200)
{
throw PeopleAgeTooBig("异常:年龄大于200");
}
if (name == NULL)
{
throw PeopleNameIsNULL("异常:名称为空");
}
if ((name[0] < 'A') || (name[0] > 'Z'))
{
throw PeopleNameErr("异常:名称错误,(name[0] < 'A') || (name[0] > 'Z')");
}
this->age = age;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
}
// People 类的析构函数
People::~People()
{
if (this->name != NULL)
{
delete[] this->name;
}
this->name = NULL;
this->age = 0;
}
//外部访问私有属性的接口
int People::get_age()
{
return this->age;
}
//重载 [] 操作符
char& People::operator[](int index)
{
return this->name[index];
}
//重载左移操作符
ostream& operator<<(ostream& out, People& p)
{
out << "name: " << p.name << " age: " << p.age << endl;
return out;
}
//People 类的内部类 构造函数,为输出字符串分配空间
People::PeopleErrType::PeopleErrType(const char* p)
{
this->err_type_str = new char[strlen(p) + 1];
strcpy(this->err_type_str, p);
}
People::PeopleErrType::~PeopleErrType()
{
if (this->err_type_str != NULL)
{
delete[] this->err_type_str;
}
this->err_type_str = NULL;
}
//异常类型:年龄太小,小于0
void People::PeopleAgeTooSmall::print_err_type()
{
cout << "err: PeopleAgeTooSmall -> " << err_type_str << endl;
}
//异常类型:年龄太大超出范围
void People::PeopleAgeTooBig::print_err_type()
{
cout << "err: PeopleAgeTooBig -> " << err_type_str << endl;
}
//异常类型:名称为空
void People::PeopleNameIsNULL::print_err_type()
{
cout << "err: PeopleNameIsNULL -> " << err_type_str << endl;
}
//异常类型:名称错误
void People::PeopleNameErr::print_err_type()
{
cout << "err: PeopleNameErr -> " << err_type_str << endl;
}
int main()
{
try
{
//通过以下4个测试例子测试4种异常
//People p(0, "Aily");
//People p(16, NULL);
//People p(300, "Aily");
//People p(16, "aily");
People p(16, "Aily");
cout << "人员信息:" << p << "\t代号:" << p[0] << p.get_age() << endl;
}
catch (People::PeopleErrType & e) //产生多态,自动识别异常类型
{
e.print_err_type();
}
catch (...)
{
cout << "其他未知异常" << endl;
}
system("pause");
return 0;
}
将测试代码依次放开,逐步调试便可以观察到程序的每一步动态
//通过以下4个测试例子测试4种异常
//People p(0, "Aily");
//People p(16, NULL);
//People p(300, "Aily");
//People p(16, "aily");
//People p(16, "Aily");