构建异常类的原因:因为当代的C++库基本上都会使用C++中的异常特性,依赖于异常创建出来的库稳定性非常好。
思路:C++中异常的类型可以是自定义类类型。
异常类的头文件:
#ifndef _EXCEPTION_H_
#define _EXCEPTION_H_
#include "Object.h"
namespace DTLib
{
#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))
class Exception : public Object
{
protected:
char* m_message; // 说明当前异常的详细信息
char* m_location; // 说明发生异常的地点
void Exception::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(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 NoEnoughMemoryException :public Exception
{
public:
NoEnoughMemoryException() : Exception(0) { }
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(0) { }
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;
}
};
// 非法操作异常
class InvalidOperationException :public Exception
{
public:
InvalidOperationException() : Exception(0) { }
InvalidOperationException(const char* message) : Exception(message) { }
InvalidOperationException(const char* file, int line) : Exception(file, line) { }
InvalidOperationException(const char* message, const char* file, int line) : Exception(message, file, line) { }
InvalidOperationException(const InvalidParameterException&e) :Exception(e)
{
}
InvalidOperationException& operator=(const InvalidParameterException&e)
{
Exception::operator =(e);
return *this;
}
};
}
#endif
异常类源文件:
#include "Exception.h"
#include <cstring>
#include <cstdlib>
using namespace std;
#pragma warning(disable:4996)
namespace DTLib
{
void Exception::init(const char* message, const char* file, int line)
{
m_message = (message ? strdup(message) : NULL);
if (file != NULL) // 发生异常的文件名
{
char sl[16] = { 0 };
itoa(line, sl, 10);
m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2)); // 2是 : \0
if (m_location != NULL)
{
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);
}
}