zoukankan      html  css  js  c++  java
  • 第11课 异常类构建

    1. 异常类构建

    (1)异常的类型可以是自定义类类型

    (2)对于类类型异常的匹配依旧是至上而下严格匹配

    (3)赋值兼容性原则在异常匹配中依然适用

    (4)一般而言,匹配子类异常的catch放在上部,匹配父类异常的catch放在下部

    (5)现代C++库必然包含充要的异常类族

    2. DTLib异常类功能定义和类图

    (1)类图结构

     

    (2)功能定义

    异常类

    功能描述

    ArithmeticException

    计算异常

    NullPointerException

    空指针异常

    IndexOutOfBoundsException

    越界异常

    NotEnoughMemoryException

    内存不足异常

    InvalidParameterException

    参数错误异常

    (3)设计原则:在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机分离正常逻辑异常逻辑

    (4)异常类中的接口定义

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

    【编程实验】创建异常类族

    //Exception.h

    #ifndef _EXCEPTION_H_
    #define _EXCEPTION_H_
    
    namespace DTLib
    {
    
    #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;
    
        //注意:
        //(1)析构函数是较为特殊的函数,一旦定义了析构函数,不管这个函数是不是纯虚函数,就
        //必须提供实现。因为,对象在销毁时,最后都会调用父类的析构函数。如果父类不提供实现,
        //当对象销毁过程中调用到父类析构函数时,就找不到析构函数,也就不知该如何析构下去。
        //因此,尽管这里将析构函数声明为纯虚函数,但Exception类仍提供析构函数的实现。以便
        //最后正确释放掉m_message和m_location所指的堆空间.
        //(2)此外,声明为纯虚函数,可以让该类只能作为接口使用,而且也强迫子类必须
        //提供析构函数的实现。
        virtual ~Exception() = 0; //纯虚函数
    };
    
    //计算异常类
    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 NotEnoughMemoryException: public Exception
    {
    public:
        NotEnoughMemoryException():Exception(0){}
        NotEnoughMemoryException(const char* message):Exception(message){}
        NotEnoughMemoryException(const char*file, int line):Exception(file, line){}
        NotEnoughMemoryException(const char *message, const char* file, int line):Exception(message, file, line){}
    
        NotEnoughMemoryException(const NotEnoughMemoryException& e): Exception(e){}
        NotEnoughMemoryException& operator=(const NotEnoughMemoryException& 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;
        }
    };
    
    }
    
    #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); //复制message的内容
    
        if(file != NULL){
            char sl[16]={0};
            itoa(line, sl, 10);//将整数line转为字符串,其中的10表示转换为十进制格式
    
            //m_location的格式为:file:line;
            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);
        }
    }
    
    //构造函数
    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(ArithmeticException, "test");
    
        }catch(const ArithmeticException& e){ //子类放catch前面
            cout << "catch(const ArithmeticException& e)" << endl;
            cout << e.message() << endl;
            cout << e.location() << endl;
    
        }catch(const Exception& e){     //父类放catch后面
            cout << "catch(const Exception& e)" << endl;
            cout << e.message() << endl;
            cout << e.location() << endl;
        }
    
        return 0;
    }

    3. 小结

    (1)现代C++库必然包含充要的异常类族

    (2)所有库中的数据结构都依赖于异常机制

    (3)异常机制能够分离库中代码的正常逻辑异常逻辑

  • 相关阅读:
    VisualSVN-Server windows 版安装时报错 "Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details."
    Pytest 单元测试框架之初始化和清除环境
    Pytest 单元测试框架入门
    Python(email 邮件收发)
    Python(minidom 模块)
    Python(csv 模块)
    禅道简介
    2020年最好的WooCommerce主题
    Shopify网上开店教程(2020版)
    WooCommerce VS Magento 2020:哪个跨境电商自建站软件更好?
  • 原文地址:https://www.cnblogs.com/5iedu/p/6748428.html
Copyright © 2011-2022 走看看