异常类知识点:
- 异常类的类型可以是自定义类型
- 对于类类型异常的匹配依旧是从上而下严格匹配
- 赋值兼容性原则在异常匹配中依然适用
- 一般而言,异常匹配中,子类异常放于catch上部,父类在下部
- 创建异常子类是为了可以抛出不同的异常来提示人们,是什么原因导致的
异常类族成员及功能:
异常类 | 功能定义 |
---|---|
Exception | 顶层抽象父类 |
ArithmeticException | 计算异常 |
NullPointerException | 空指针异常 |
IndexOutOfBoundsException | 越界异常 |
NoEnoughMemoryException | 内存不足异常 |
InvalidParameterException | 参数错误异常 |
异常类设计原则:
- 在可复用代码库设计时尽量使用面向对象技术进行架构
- 尽量使用异常处理机制分离正常逻辑与异常逻辑
异常类中的接口定义:
//利用宏快速的扔出异常
#define THROW_EXCEPTION(e,m) throw(e(m,__FILE__,__LINE__))//扔出一个e类型对象的异常
class Exception:public Object //顶层抽象父类
{
protected:
char* m_message;//异常信息
char* m_location;//异常位置
void init(const char* message,const char* file,int line);
public:
Exception(const char* message);
Exception(const char* file,int line);
Exception(const char* message,const char* file,int line);
Exception(const Exception& e);
Exception& operator =(const Exception& e);
virtual const char* message()const;
virtual const char* location()const;
virtual ~Exception()=0;//纯虚函数,抽象类,只能继承,不能创建对象
};
异常类的具体实现:
#include "Exception.h"
#include <cstdlib>
#include <cstring>
using namespace std;
namespace JYlib
{
void Exception::init(const char* message,const char* file,int line)
{
m_message = (message != NULL ? strdup(message) : NULL);//申请内存空间,拷贝字符串,返回地址,需要free
if( file != NULL)
{
char str1[16]={0};
itoa(line,str1,10);//待转换的整数值,存储的字符串,转换为几进制数的字符串
m_location = reinterpret_cast<char*>(malloc(strlen(file) + strlen(str1) + 2));//多申请的两个字节,存放:与末尾的/0
if(m_location != NULL)
{
m_location = strcpy(m_location,file);//将file拷贝(覆盖)到m_location
m_location = strcat(m_location,":");//拼接,:接在m_location后面
m_location = strcat(m_location,str1);
}
//这里不能抛出内存不足异常,因为内存不足异常是该类的子类,创建的时候会重新进人该函数,所以直接不处理
}
else
{
m_location = NULL;
}
}
Exception::Exception(const char* message,const char* file,int line)
{
init(message,file,line);
}
Exception::Exception(const char* file,int line)
{
init(NULL,file,line);
}
Exception::Exception(const char* message)
{
init(message,NULL,0);
}
Exception::Exception(const Exception& e)//深拷贝
{
m_message = strdup(e.m_message);
m_location = strdup(e.m_location);
}
Exception& Exception::operator = (const Exception& e)//深拷贝
{
if(this != &e)//拷贝构造一定要判断是否为本身
{
free(m_message);//先释放原来的内容
free(m_location);
m_message = strdup(e.m_message);
m_location = strdup(e.m_location);
}
return *this;
}
const char* Exception::message()const
{
return m_message;
}
const char* Exception::location()const
{
return m_location;
}
Exception::~Exception()
{
free(m_message);
free(m_location);
}
}
异常子类的实现:这里举一个例子,其余的异常子类实现方式相同
class ArithmeticException : public Exception //计算异常
{
public:
ArithmeticException() : Exception(NULL,NULL,0){}
ArithmeticException(const char* message) : Exception(message,NULL,0){}
ArithmeticException(const char* file,int line) : Exception(NULL,file,line){}
ArithmeticException(const char* message,const char* file,int line) : Exception(message,file,line){}
ArithmeticException(const ArithmeticException& e) : Exception(e){}
ArithmeticException& operator =(const ArithmeticException& e)
{
Exception::operator=(e);
return *this;
}
};