打造可复用的数据结构库——2 异常类族的构建

1 为什么有异常类族

​ 在程序的逻辑处理的时候,会有一些异常的现象,这种情况,我们只能预测他可能出现,但是却无法彻底的避免,则就要在一些会出现异常的地方做些防御,一旦出现异常,就要有相应的处理对策。

2 异常类的构建

​ 一个工程中,代码的逻辑是错综复杂,则就要有一定的章程来管理异常的处理,这样,可以帮助我们的程序看起来干净整洁。在现在的工程中,常见的异常一般有:

  1. 计算异常;例如做了除以0的操作
  2. 空指针异常:例如对空指针做了不合法的操作
  3. 访问越界异常
  4. 内存不足异常
  5. 参数错误异常

​ 异常情况的整理与分类,我们可以看出,这些异常有一定的共性,但也有不同的地方。我们就利用C++语言语言的继承与多态的特性,做一个基础的异常类,然后各个类从基础类继承,然后自己添加自己的特性。

2.1 异常类的基类构建

2.1.1 提示函数

​ 既然是异常的类,他的出现,就是为了告警,那么就会有一些提示信息,实际使用的使用,都是抛出异常的地方输入一些提示语句。那么构建类的时候,就要设计提示语句的输入的地方。

Exceptional(const char *message);
Exceptional(const char *file, int line);
Exceptional(const  char *message, const char *file,const int line);

virtual const char *message() const;
virtual const char * location( ) const ;

​ 从这三个构建函数的样子可以看出,基本是一样的,就是个别的参数没有而已,为了代码的复用,可以写一个公用的私有函数来做三个构建函数的实现。

 void init(const char *message, const char *file, int line);
2.1.2 属性工能函数

​ 既然是类,就要符合C++的类的一般共性,但是该类在 赋值操作的时候,或者拷贝构造的时候,就需要特殊处理,则需要对这两个工能做处理

Exceptional(const Exceptional&  obj);
Exceptional& operator = ( const  Exceptional& obj);

2.2 类的架构

​ 以上的描述已经基本可以构造这个类了,但是有个细节要注意,就是在传入的字符串存储空间是无法确定的。为了防止意外,该类要对传入的字符串做一个复制,在函数被析构的时候,就要释放。所以类的构造如下。

    class Exceptional
    {
    protected:
        char* m_message=nullptr;
        char* m_location =nullptr;
        
        void init(const char *message, const char *file, int line);
    public:
        Exceptional(const char *message);
        Exceptional(const char *file, int line);
        Exceptional(const  char *message, const char *file,const int line);

        Exceptional(const Exceptional&  obj);
        Exceptional& operator = ( const  Exceptional& obj);

        virtual const char *message() const;
        virtual const char * location( ) const ;

        virtual  ~Exceptional() =0 ;

    };

3基类的实现

     void Exceptional :: init(const char *message, const char *file, const int line)
     {
         //因为不能保证传进来的 message 的空间,所以复制一份存到堆中
         m_message= strdup(message);

         if(file != NULL)
         {
             char sl[16]={0};
             itoa(line,sl,10);
             m_location=reinterpret_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=nullptr;
         }
     }

    Exceptional :: Exceptional(const char *message)
    {
         init( message, NULL, NULL);
    }

    Exceptional :: Exceptional(const char *file, int line)
    {
        init( NULL, file, line);
    }

    Exceptional :: Exceptional( const char *message, const char *file,const int line)
    {
         init( message, file, line);
    }


    Exceptional :: Exceptional( const Exceptional&  obj)
    {
        m_message= strdup(obj.m_message);
        m_location= strdup(obj.m_location);
    }

    Exceptional& Exceptional :: operator = ( const  Exceptional& obj)
    {
        if(this != &obj)
        {
            free(m_message);
            free(m_location);

            m_message= strdup(obj.m_message);
            m_location= strdup(obj.m_location);
        }

        return *this;
    }


    const char * Exceptional :: message() const
    {
        return m_message;
    }

    const char * Exceptional :: location( ) const
    {
        return m_location;
    }


    Exceptional ::  ~Exceptional()
    {
        free(m_message);
        free(m_location);
    }

4 继承类的实现

基类完成以后,剩下的就是对各自类的具体实现、

4.1 计算异常类的实现

    /****************************************************
     *  class ArithmeticExcption  计算异常
     ****************************************************
     * */
    class ArithmeticExcption :public Exceptional
    {
    public:
        ArithmeticExcption() : Exceptional(nullptr) {}
        ArithmeticExcption(const char  * message ) : Exceptional( message ) {}
        ArithmeticExcption(const char *file, int line): Exceptional( file, line ) {}
        ArithmeticExcption(const  char *message, const char *file,const int line):Exceptional(message, file, line){}

        ArithmeticExcption(const  ArithmeticExcption & obj) : Exceptional(obj ){}

        ArithmeticExcption& operator = (const ArithmeticExcption & obj)
        {
            Exceptional::operator = ( obj);
            return *this ;
        }
    };

4.2 空指针异常

    /****************************************************
     *  class NullPointerExcption   空指针异常
     ****************************************************
     * */
    class NullPointerExcption :public Exceptional
    {
    public:
        NullPointerExcption() : Exceptional(nullptr) {}
        NullPointerExcption(const char  * message ) : Exceptional( message ) {}
        NullPointerExcption(const char *file, int line): Exceptional( file, line ) {}
        NullPointerExcption(const  char *message, const char *file,const int line):Exceptional(message, file, line){}

        NullPointerExcption(const  NullPointerExcption & obj) : Exceptional(obj ){}

        NullPointerExcption& operator = (const NullPointerExcption & obj)
        {
            Exceptional::operator = ( obj);
            return *this ;
        }
    };

4.3 访问越界异常

    /****************************************************
     *  class IndexOutOfBoundsException   访问越界异常
     ****************************************************
     * */
    class IndexOutOfBoundsException :public Exceptional
    {
    public:
        IndexOutOfBoundsException() : Exceptional(nullptr) {}
        IndexOutOfBoundsException(const char  * message ) : Exceptional( message ) {}
        IndexOutOfBoundsException(const char *file, int line): Exceptional( file, line ) {}
        IndexOutOfBoundsException(const  char *message, const char *file,const int line):Exceptional(message, file, line){}

        IndexOutOfBoundsException(const  IndexOutOfBoundsException & obj) : Exceptional(obj ){}

        IndexOutOfBoundsException& operator = (const IndexOutOfBoundsException & obj)
        {
            Exceptional::operator = ( obj);
            return *this ;
        }
    };

4.4 内存不足异常

    /****************************************************
     *  class NoEnoughMemoryException   内存不足异常
     ****************************************************
     * */
    class NoEnoughMemoryException :public Exceptional
    {
    public:
        NoEnoughMemoryException() : Exceptional(nullptr) {}
        NoEnoughMemoryException(const char  * message ) : Exceptional( message ) {}
        NoEnoughMemoryException(const char *file, int line): Exceptional( file, line ) {}
        NoEnoughMemoryException(const  char *message, const char *file,const int line):Exceptional(message, file, line){}

        NoEnoughMemoryException(const  NoEnoughMemoryException & obj) : Exceptional(obj ){}

        NoEnoughMemoryException& operator = (const NoEnoughMemoryException & obj)
        {
            Exceptional::operator = ( obj);
            return *this ;
        }
    };

4.5 参数异常

    /****************************************************
     *  class InvalidParameterExcetion   参数异常
     ****************************************************
     * */
    class InvalidParameterExcetion :public Exceptional
    {
    public:
        InvalidParameterExcetion() : Exceptional(nullptr) {}
        InvalidParameterExcetion(const char  * message ) : Exceptional( message ) {}
        InvalidParameterExcetion(const char *file, int line): Exceptional( file, line ) {}
        InvalidParameterExcetion(const  char *message, const char *file,const int line):Exceptional(message, file, line){}

        InvalidParameterExcetion(const  InvalidParameterExcetion & obj) : Exceptional(obj ){}

        InvalidParameterExcetion& operator = (const InvalidParameterExcetion & obj)
        {
            Exceptional::operator = ( obj);
            return *this ;
        }
    };

5 使用注意

类的父子兼容性原则,做catch 时,把子类写在前边。

你可能感兴趣的