数据结构C++语言实现--准备工作二(异常类)

发布于 2023-6-13 15:15
浏览
0收藏

数据结构C++语言实现系列文章的代码实现在智能指针、异常类、顶层父类三大基础类上进行代码实现,本文件介绍异常类。

数据结构C++语言实现--准备工作二(异常类) -汽车开发者社区

1.异常类介绍

C++异常的类型可以是自定义类类型,对于类类型异常的匹配依旧是自上而下严格匹配,赋值兼容性原则在异常匹配中依旧适用。一般而言,匹配子类异常的catch放在上部,匹配父类异常的catch放在下部分。

2.异常类的设计

Exception: 抽象异常类,声明异常类接口,是所有异常类的顶层父类。

ArithmeticException: 计算异常类

NullPointerException: 空指针异常类

IndexOutOfBoundsException: 越界异常类

NoEnoughMemoryException: 内存不足异常类

InvalidParameterException: 参数错误异常类


数据结构C++语言实现--准备工作二(异常类) -汽车开发者社区

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;
}

数据结构C++语言实现--准备工作二(异常类) -汽车开发者社区

异常类能够使得异常逻辑和正常逻辑分离,异常处理中通过抛出具体的异常类,能够轻易的或者程序异常的类型及异常代码的文件位置。

4.小结

异常机制能够分离数据结构库中代码的正常逻辑异常逻辑,在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑


Note: 数据结构实践系列文章中用到了非常多的C++和C语言知识,数据结构系列文章中不再重复讲解,具体可以参考本公众号中C/C++系列文章。


参考资料:《C++ primer》

                《C++对象模型》

                狄泰软件学院唐佐林老师课程


文章转载自公众号:汽车电子嵌入式


分类
收藏
回复
举报
回复
相关推荐