我们在之前学习了 C++ 中有关异常的知识,现在我们来重新回顾下。那么异常的格式是什么呢?便是 try ... catch ...;try 语句处理正常的代码逻辑,而 catch 语句则处理异常情况,try 语句中的异常由对应的 catch 语句处理。格式如下
try
{
double r = divide(1, 0);
}
catch(...)
{
cout << "Divided by zero ..." << endl;
}
在 C++ 中,通过 throw 语句抛出异常信息。throw 抛出的异常必须被 catch 处理,当前函数如果能处理异常,程序将继续往下执行;如果当前函数无法处理异常则函数停止执行并返回。未被处理的异常会顺着函数调用栈向上传播,直到被处理为止,否则程序将停止执行。如下
同一个 try 语句可以跟上多个 catch 语句。catch 语句可以定义具体处理的异常类型,不同类型的异常由不同的 catch 语句负责处理;try 语句中可以抛出任何类型的异常,catch(...) 用于处理所有类型的异常,任何异常都只能被捕获(catch)一次。异常处理的匹配规则如下
异常的类型可以是自定义类类型,对于类类型异常的匹配依旧是至上而下严格匹配,赋值兼容性原则在异常匹配中依然适用。一般而言:匹配子类异常的 catch 放在上部,匹配父类异常的 catch 放在下部。现代 C++ 库中必然包含充要的异常类族,因为异常类是数据结构类所依赖的“基础设施”!举个例子,如果我们在申请内存失败时便要但会一个内存不足的异常。异常类如下图所示
下来我们来看看异常类功能定义,如下
下来我们来创建一个异常类族,代码如下
Exception.h 源文件
#ifndef EXCEPTION_H#define EXCEPTION_H
#include "Object.h"
namespace DTLib
{
class Exception : public Object
{
private:
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();
};
#endif // EXCEPTION_H
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 s1[16] = {0};
itoa(line, s1, 10);
m_location = static_cast<char*>(malloc(strlen(file) + strlen(s1) + 2));
m_location = strcpy(m_location, file);
m_location = strcat(m_location, ":");
m_location = strcat(m_location, s1);
}
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>#include "Exception.h"
using namespace std;
using namespace DTLib;
int main()
{
try
{
throw Exception("test", __FILE__, __LINE__);
}
catch(const Exception& e)
{
cout << "catch(const Exception& e)" << endl;
cout << e.message() << endl;
cout << e.location() << endl;
}
return 0;
}
下来我们来看看编译结果
我们看到抛出了一个异常,它的文件名是 test,行号是 11 行。我们可以在 Exception.h 头文件添加一个宏,用来显示文件名及行号,定义如下
#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))
然后将 mian.cpp 中的 throw 语句中的抛异常改为下面这样
THROW_EXCEPTION(Exception, "test");
编译结果如下
我们看到效果是一样的。那么在可复用代码库设计时,尽量使用卖你想对象技术进行架构,尽量使用异常处理机制分类正常逻辑和异常逻辑。通过今天对异常类的学习,总结如下:1、C++ 中国直接支持异常处理的概念,try ... catch ... 是 C++ 中异常处理的专用语句;2、try 语句处理的是正常代码逻辑,catch 语句处理的是异常情况;3、同一个 try 语句可以跟上多个 catch 语句,异常处理必须严格匹配,不进行任何的类型转换;4、现代 C++ 库必然包含充要的异常类族,所有库中的数据结构都依赖于异常机制;5、异常机制能够分离库中代码的正常逻辑个异常逻辑。
转载于:https://blog.51cto.com/12810168/2156990