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

构造函数和析构函数没有返回值,不能像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");
posted @ 2022-03-17 10:00  Mindtechnist  阅读(8)  评论(0编辑  收藏  举报  来源