数据结构-(1 1)-异常类构建

异常类构建:

  • 异常的类型可以是自定义 类类型
  • 对于 类类型异常 的匹配依旧是至上而下严格匹配
  • 赋值兼容性原则 在异常匹配中依然适用
  • 一般而言
    – 匹配子类异常的 catch 放在上部
    – 匹配父类异常的 catch 放在下部
  • 现代c++库必然包所依赖的异常类族

这里写图片描述

  • 异常类中的接口定义
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() = 0;

};
  • 设计原则
    –在可服用代码库设计时,尽量适用面向对象技术进行架构,尽量使用异常处理机制 分离正常逻辑和异常逻辑

  • 现代c++库中必然包含充要的异常类族

  • 所有库中的数据结构都依赖于异常机制
  • 异常机制能够分离库中代码的正常逻辑和异常逻辑

以下为实现自己的异常库MyLib部分代码

file:Exception.h

namespace MyLib {

#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;
    }
};
}
file:Exception.cpp

namespace MyLib
{
    void Exception::init(const char *message, const char *file, int line)
    {
        //参数message是一个指针,指向的字符串 有可能 在栈上、堆上、全局数据区,没法控制指向的字符串的声明周期.
        //所以说这样是不安全的(m_message = message),可能被释放,所以需要拷贝一份信息.
        m_message = strdup(message);//字符串复制一份到堆空间,m_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);
}

}
file:main.cpp

#include <iostream>
#include "Exception.h"


using namespace std;
using namespace MyLib;

int main()
{
    cout << "Hello World!" << endl;
    try
    {
        //throw Exception("test",__FILE__,__LINE__);
        //THROW_EXCEPTION(NullPointerException,"test");
        //扔出子类对象,子类对象可以出现在任何父类需要对象的地方
        THROW_EXCEPTION(ArithmeticException,"test");
    }
    catch(const ArithmeticException& e)
    {
        cout<<"catch(const ArithmeticException& e)"<<endl;

        cout<< e.message()<<endl;
        cout<< e.location()<<endl;

    }
    catch(const Exception& e)//父类放在最后
    {
        cout<<"catch(const Exception& e)"<<endl;

        cout<< e.message()<<endl;
        cout<< e.location()<<endl;

    }
    return 0;

运行结果:

Hello World!
catch(const ArithmeticException& e)
test
..\MyLib\main.cpp:18

学习内容来自D.T.Software的数据结构课程,希望可以和大家一起学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值