- 异常的类型可以是自定义类类型
- 对于类类型异常的匹配依旧是至上而下严格匹配
- 赋值兼容性原则在异常匹配中依然适用
一般而言
- 匹配子类异常的 catch 放在上部
- 匹配父类异常的 catch 放下下部
现代C++库必然包含充要的异常类
异常类是数据结构类所依赖的”基础设施“!
异常类功能定义
异常类 | 功能定义 |
ArithmeticException | 计算异常 |
NullPointerException | 空指针异常 |
IndexOutOfBoundsException | 越界异常 |
NoEnoughMemoryException | 内存不足异常 |
InvalidParameterExcetion | 参数错误异常 |
异常类的接口定义
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();
};
编程实验:创建异常类族
文件:Exception.h
#ifndef EXCEPTION_H
#define EXCEPTION_H
namespace DTLib
{
#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))
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();
protected:
char *m_message = nullptr;
char *m_location = nullptr;
};
class ArithmeticExcption : public Exception
{
public:
ArithmeticExcption() : Exception(nullptr) { }
ArithmeticExcption(const char *message) : Exception(message) { }
ArithmeticExcption(const char *file, int line) : Exception(file, line) { }
ArithmeticExcption(const char *message, const char *file, int line) : Exception(message, file, line) { }
ArithmeticExcption(const ArithmeticExcption &e) : Exception(e) { }
ArithmeticExcption &operator= (const ArithmeticExcption &e)
{
Exception::operator=(e);
return *this;
}
~ArithmeticExcption() override { }
};
class NullPointerException : public Exception
{
public:
NullPointerException() : Exception(nullptr) { }
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 ArithmeticExcption &e) : Exception(e) { }
NullPointerException &operator= (const ArithmeticExcption &e)
{
Exception::operator=(e);
return *this;
}
~NullPointerException() override { }
};
class IndexOutOfBoundsException : public Exception
{
public:
IndexOutOfBoundsException() : Exception(nullptr) { }
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 ArithmeticExcption &e) : Exception(e) { }
IndexOutOfBoundsException &operator= (const ArithmeticExcption &e)
{
Exception::operator=(e);
return *this;
}
~IndexOutOfBoundsException() override { }
};
class NoEnoughMemoryException : public Exception
{
public:
NoEnoughMemoryException() : Exception(nullptr) { }
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 ArithmeticExcption &e) : Exception(e) { }
NoEnoughMemoryException &operator= (const ArithmeticExcption &e)
{
Exception::operator=(e);
return *this;
}
~NoEnoughMemoryException() override { }
};
class InvalidParameterExcetion : public Exception
{
public:
InvalidParameterExcetion() : Exception(nullptr) { }
InvalidParameterExcetion(const char *message) : Exception(message) { }
InvalidParameterExcetion(const char *file, int line) : Exception(file, line) { }
InvalidParameterExcetion(const char *message, const char *file, int line) : Exception(message, file, line) { }
InvalidParameterExcetion(const ArithmeticExcption &e) : Exception(e) { }
InvalidParameterExcetion &operator= (const ArithmeticExcption &e)
{
Exception::operator=(e);
return *this;
}
~InvalidParameterExcetion() override { }
};
}
#endif // EXCEPTION_H
文件:Exception.cpp
#include "Exception.h"
#include
#include
namespace DTLib
{
Exception::Exception(const char *message) : Exception(message, nullptr, 0)
{
}
Exception::Exception(const char *file, int line) : Exception(nullptr, file, line)
{
}
Exception::Exception(const char *message, const char *file, int line)
{
m_message = strdup(message);
if (file != nullptr)
{
char sl[16] = {0};
itoa(line, sl, 10);
m_location = static_cast(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 = nullptr;
}
}
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()
{
delete m_message;
delete m_location;
}
}
文件:main.cpp
catch (const ArithmeticExcption &e)
TEST
..\DTLib\main.cpp:13
设计原则
在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑。
小结
- 现在C++库必要包含充要的异常类族
- 所有库中的数据结构都依赖于异常机制
- 异常机制能够分离库中代码的正常逻辑和异常逻辑
以上内容整理于狄泰软件学院系列课程,请大家保护原创!