
数据结构C++语言实现--准备工作二(异常类)
数据结构C++语言实现系列文章的代码实现在智能指针、异常类、顶层父类三大基础类上进行代码实现,本文件介绍异常类。
1.异常类介绍
C++异常的类型可以是自定义类类型,对于类类型异常的匹配依旧是自上而下严格匹配,赋值兼容性原则在异常匹配中依旧适用。一般而言,匹配子类异常的catch放在上部,匹配父类异常的catch放在下部分。
2.异常类的设计
Exception: 抽象异常类,声明异常类接口,是所有异常类的顶层父类。
ArithmeticException: 计算异常类
NullPointerException: 空指针异常类
IndexOutOfBoundsException: 越界异常类
NoEnoughMemoryException: 内存不足异常类
InvalidParameterException: 参数错误异常类
3.代码实现
/*===========================================================
* 文件:异常类
* 日期:2021-9-4
* 设计人:Tomas
*
* 异常类的要求:
* 1.
* 2.
* 3.
* ========================================================*/
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include "Object.h"
namespace DataStructLib {
#define THROW_EXCEPTION(e,m) (throw e(m,__FILE__,__LINE__))
class Exception:public Object
{
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 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 InvalidOperationException &e):Exception(e){}
InvalidOperationException& operator =(const InvalidParameterException& e)
{
Exception::operator =(e);
return *this;
}
};
}
#endif // EXCEPTION_H
#include "Exception.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace DataStructLib {
void Exception::init(const char* message,const char* file,int line)
{
//参数 message 这个指针指向的内容可能在栈上 堆空间 全局数据区 要是 m_message=message 这
//样赋值是不安全的 我们无法控制数据的生命周期 解决方案==>拷贝一份
//m_message = strdup(message); //
m_message = (message ? strdup(message) : NULL);//strdup()函数的内部动态分配了堆空间
if(file != NULL)
{
char sl[16] = {0};
itoa(line,sl,10);//10 表示转换的为 10 进制数
m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
if(m_location)
{
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);
}
}
#include <iostream>
#include "Exception.h"
using namespace std;
using namespace DataStructLib;
int main()
{
try
{
THROW_EXCEPTION(ArithmeticException,"test");//使用这个宏的意义在于我们在使用这个宏的地方直接扔出
} //相应的异常对象就行了 具体的文件名和行号这个宏会自动添加
catch(const Exception& e) //赋值兼容捕获
{
cout << "catch(const Exception& e)" << endl;
cout << e.message() << endl;
cout << e.location() << endl;
}
catch(const ArithmeticException& e)
{
cout << "catch(const ArithmeticException& e)" << endl;
cout << e.message() << endl;
cout << e.location() << endl;
}
return 0;
}
异常类能够使得异常逻辑和正常逻辑分离,异常处理中通过抛出具体的异常类,能够轻易的或者程序异常的类型及异常代码的文件位置。
4.小结
异常机制能够分离数据结构库中代码的正常逻辑和异常逻辑,在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑。
Note: 数据结构实践系列文章中用到了非常多的C++和C语言知识,数据结构系列文章中不再重复讲解,具体可以参考本公众号中C/C++系列文章。
参考资料:《C++ primer》
《C++对象模型》
狄泰软件学院唐佐林老师课程
文章转载自公众号:汽车电子嵌入式
分类
标签
赞
收藏
回复

回复
相关推荐