现在C++库必然包含充要的异常类族,异常类族是数据结构类所依赖的"基础设施", 如下图是该异常类族的类图,顶层的类是一个抽象类,它是不能定义对象的,只能用来被继承,从左向右的异常类分别为计算异常,空指针异常,越界异常,内存不足异常,参数错误异常,
顶层抽象父类的接口定义:
Exception.h
class Exception
{
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;//纯虚析构函数
}
在项目的设计原则中,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑,代码如下
#ifndef _EXCEPTION_H
#define _EXCEPTION_H
namespace CGSLib
{
#define THROW_EXCEPTION(m,s) (m(s,__FILE__,__LINE__))
class Exception
{
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();//纯虚析构函数
};
class ArithmeticException : public Exception
{
public:
ArithmeticException():Exception(0){}
ArithmeticException(const char *message):Exception(message){}
ArithmeticException(const char *file,int line):Exception(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;
}
};
class NullPointerException : public Exception
{
public:
NullPointerException():Exception(0){}
NullPointerException(const char *message):Exception(message){}
NullPointerException(const char *file,int line):Exception(file,line){}
NullPointerException(const char *message,const char *file,int line):Exception(message,file,line){}
NullPointerException(const NullPointerException& e):Exception(e){}
NullPointerException& operator=(const NullPointerException& e)
{
Exception::operator =(e);
return *this;
}
};
class IndexOutOfBoundsException : public Exception
{
public:
IndexOutOfBoundsException():Exception(0){}
IndexOutOfBoundsException(const char *message):Exception(message){}
IndexOutOfBoundsException(const char *file,int line):Exception(file,line){}
IndexOutOfBoundsException(const char *message,const char *file,int line):Exception(message,file,line){}
IndexOutOfBoundsException(const IndexOutOfBoundsException& e):Exception(e){}
IndexOutOfBoundsException& operator=(const IndexOutOfBoundsException& e)
{
Exception::operator =(e);
return *this;
}
};
class NoEnougMemoryException : public Exception
{
public:
NoEnougMemoryException():Exception(0){}
NoEnougMemoryException(const char *message):Exception(message){}
NoEnougMemoryException(const char *file,int line):Exception(file,line){}
NoEnougMemoryException(const char *message,const char *file,int line):Exception(message,file,line){}
NoEnougMemoryException(const NoEnougMemoryException& e):Exception(e){}
NoEnougMemoryException& operator=(const NoEnougMemoryException& e)
{
Exception::operator =(e);
return *this;
}
};
class InvalidParamterException : public Exception
{
public:
InvalidParamterException():Exception(0){}
InvalidParamterException(const char *message):Exception(message){}
InvalidParamterException(const char *file,int line):Exception(file,line){}
InvalidParamterException(const char *message,const char *file,int line):Exception(message,file,line){}
InvalidParamterException(const InvalidParamterException& e):Exception(e){}
InvalidParamterException& operator=(const InvalidParamterException& e)
{
Exception::operator =(e);
return *this;
}
};
}
#endif // EXCEPTION_H
Exception.cpp
#include "Exception.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace CGSLib
{
void Exception::init(const char *message,const char *file,int line)
{
m_message = strdup(message);
if(file!=NULL)
{
char str[16]={0};
itoa(line,str,10);
m_location = static_cast<char*>(malloc(sizeof(file)+sizeof(line)+2));
m_location = strcpy(m_location,file);
m_location = strcat(m_location,":");
m_location = strcat(m_location,str);
}
else
{
m_location = NULL;
}
}
Exception::Exception(const char *message)
{
init(message,NULL,0);
}
Exception::Exception(const char *file,int line)
{
init(NULL,file,line);
}
Exception::Exception(const char *message,const char *file,int line)
{
init(message,file,line);
}
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);
}
}
main.cpp
#include <iostream>
using namespace std;
#include <iostream>
#include "Exception.h"
using namespace std;
using namespace CGSLib;
int main()
{
try
{
throw THROW_EXCEPTION(InvalidParamterException,"test");
}catch(const Exception & e)
{
cout<<"catch(const Exception& e)"<<endl;
cout<<e.message()<<endl;
cout<<e.location()<<endl;
}
}
结果:
当代软件架构实践的经验
尽量使用单重继承的方式进行系统设计
尽量保持系统中只存在单一的继承树
尽量使用组合关系代替继承关系