配套环境
clion + mingw
设计要求
异常的类型可以是自定义类类型
对于类类型异常的匹配依旧是自上而下严格匹配
赋值兼容性原则在异常匹配中依然适用
一般而言: 匹配子类异常的catch放在上部
匹配父类异常的catch放在下部
设计方案
实现代码
Exception.cpp
#include "Exception.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace DTLib {
void Exception::init(const char *message, const char *file, int line) {
m_message = _strdup(message);
if(file != NULL){
char sl[16] = {0};
itoa(line, sl, 10);
m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
m_location = strcpy(m_location, file);
m_location = strcat(m_location, ":");
m_location = strcat(m_location, sl);
}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);
}
} // namespace DTLib
Exception.h
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include <cstring>
namespace DTLib {
#define THROW_EXCEPTION(e,m) (throw e(m, __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() = 0;
};
class ArithmeticException : public Exception{
public:
ArithmeticException() : Exception(NULL){}
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(NULL){}
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(NULL){}
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 NoEnoughMemoryException : public Exception{
public:
NoEnoughMemoryException() : Exception(NULL){}
NoEnoughMemoryException(const char * message) : Exception(message){}
NoEnoughMemoryException(const char * file, int line) : Exception(file, line){}
NoEnoughMemoryException(const char * message, const char* file, int line) : Exception(message, file, line){}
NoEnoughMemoryException(const NoEnoughMemoryException& e) : Exception(e){}
NoEnoughMemoryException& operator=(const NoEnoughMemoryException& e){
Exception::operator=(e);
return *this;
}
};
class InvalidParameterException : public Exception{
public:
InvalidParameterException() : Exception(NULL){}
InvalidParameterException(const char * message) : Exception(message){}
InvalidParameterException(const char * file, int line) : Exception(file, line){}
InvalidParameterException(const char * message, const char* file, int line) : Exception(message, file, line){}
InvalidParameterException(const InvalidParameterException& e) : Exception(e){}
InvalidParameterException& operator=(const InvalidParameterException& e){
Exception::operator=(e);
return *this;
}
};
} // namespace DTLib
#endif
设计原则
在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑
小结
现代C++库必然包含充要的异常类族
所有库中的数据结构类都依赖于异常机制
异常机制能够分离库中代码的正常逻辑和异常逻辑
喝水不忘挖井人: 更多内容请搜索狄泰软件学院(淘宝/B站)