zoukankan      html  css  js  c++  java
  • 异常类之基类

    1.C++中的异常

    C++异常处理语法元素try-catch语句
    • try语句处理正常代码逻辑  (但有可能产生异常,产生异常时抛出异常并转到catch语句块里面的代码)
    • catch语句处理异常情况
    • try语句中的异常由对应的catch语句处理
    • C++通过throw语句抛出异常信息(一般在try语句中)
    throw和return区别
    throw异常的返回一个值,这个值就代表了异常,   抛到catch语句块 
    return正常的返回一个值
     
    C++异常处理分析
    (1)throw抛出的异常必须catch处理
    • 当前函数能够处理异常(含有catch语句块,程序继续往下执行
    • 当前函数无法处理异常,则函数停止执行并返回,由上层函数进行处理了
    (2)未被处理的异常会顺着函数调用栈向上传播,直到被处理为止,否则程序将停止执行。如果一直未处理则会到main函数,该函数中若果仍没有try..catch语句直接退出
     

    (3)同一个try语句可以跟上多个catch语句

      ①catch语句可以定义具体处理的异常类型

      ②不同类型的异常由不同的catch语句负责处理

      ③try语句中可以抛出任何类型的异常

      ④catch(…)用于处理所有类型的异常

      ⑤任何异常都只能被捕获(catch)一次

    (4)异常处理的匹配规则

     

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 double divide(double a, double b)
     6 {
     7     const double delta = 0.000000000000001;
     8     double ret = 0;
     9 
    10     if( !((-delta < b) && ( b < delta))){
    11         ret = a / b;
    12     }else{
    13         throw 0; //产生除0异常
    14     }
    15 
    16     return ret;
    17 }
    18 
    19 //匹配规则(自上而下,严格匹配、不进行类型转换)
    20 void Demo1()
    21 {
    22     try{
    23         throw 'c';  //抛出字符型的异常
    24     }catch(int i){
    25         cout << "catch(int i)" << endl;
    26     }catch(double d){
    27         cout << "catch(double d)" << endl;
    28     }catch(char c){ //只能被这里的catch捕获
    29         cout << "catch(char c)" << endl;
    30     }
    31 }
    32 
    33 void Demo2()
    34 {
    35     throw "Demo2";   //const char*
    36 }
    37 int main()
    38 {
    39     cout << "main() begin" << endl;
    40 
    41     try{
    42         double c = divide(1, 0);//产生异常
    43         cout <<"c = " << c << endl; //无法被执行到!
    44     }catch(...){
    45         cout << "Divide by zero..." << endl;
    46     }
    47 
    48     Demo1();
    49 
    50     try{
    51         Demo2();
    52 53       catch(char* c)
    54      {
    55         cout << "catch(char* c)" << endl;
    56     }
    57     catch(const char* c)
    58         {
    59         cout << "catch(const char* c)" << endl;
    60     }catch(...)
    61      {
    62        //写位置最后
    63         cout << "catch(...)" << endl;
    64     }
    65 
    66     cout << "main() end" << endl;
    67     return 0;
    68 }
    View Code

    2.异常类的构建

    • 异常的类型可以是定义类型
    • 对于类类型异常的匹配依旧是至上而下严格匹配(不能强制类型的转换)
    • 赋值兼容性原则(子类的对象可以直接复制给父类的对象,父类的指针可以直接指向子类的对象在异常匹配中依然使用 (出现父类对象是可以用一个子类对象代替)
    • 一般而言:
        ------匹配子类异常的catch放在上部
        ------匹配父类异常的catch放在下部

    3、异常类族

    现代C++库必然包含充要的异常类族 
    异常类族是数据结构类所以来的“基础设施
     
     顶层父类Exception是一个抽象类,不能定义对象,用于被继承的。
    这一节就是实现这个抽象基类的。
    目的:当程序抛出异常时(有可能会是一个字符串、文件名、行号),能够捕捉到这个异常,并打印处异常的信息等。
    要实现的几个函数:
    构造函数:对收到的异常进行初始化工作
    1     Exception(const char* message); 
    2     Exception(const char* file,int line);
    3     Exception(const char* message,const char* file,int line);

    由于初始化工作差不多,为了代码整洁我们将相同的操作封装成了一个函数即:

    void  init(const char*,const char*,int);//由于三个构造函数中的逻辑很相似,所以可以将相似的部分统一放到一个函数init()

    此外还需要保存一些初始化变量的成员变量

    1 char* m_message;//m_message指向一个字符串,用于说明当前的异常信息
    2 char* m_location;//m_location指向一个字符串,用于说明当前的异常位置

    由于涉及到堆空间即需进行深拷贝,就不能使用默认的拷贝构造函数和赋值操作符,需要自己定义实现即

    1 //涉及到堆空间即需进行深拷贝,拷贝构造函数和"="
    2     Exception(const Exception& e);
    3     Exception& operator =(const Exception& e);

    完整代码如下

    Exception.h 

     1 #ifndef _EXCEPTION_H_
     2 #define _EXCEPTION_H_ 
     3 namespace DataStructureLib
     4 {
     5 
     6 class Exception
     7 {
     8 protected:
     9     char*  m_message;
    10     char*  m_location;
    11 protected:
    12     void  init(const char*,const char*,int);//由于三个构造函数中的逻辑很相似,所以可以将相似的部分统一放到一个函数init()
    13 public:
    14     Exception(const char* message); 
    15     Exception(const char* file,int line);
    16     Exception(const char* message,const char* file,int line);
    17 
    18     //涉及到堆空间即需进行深拷贝,拷贝构造函数和"="
    19     Exception(const Exception& e);
    20     Exception& operator =(const Exception& e);
    21 
    22     virtual const char* message() const;
    23     virtual const char* location() const;
    24 
    25     virtual ~Exception(void);
    26 };
    27 #endif
    28 }

    Exception.cpp 

     1 #include "Exception.h"
     2 #include <cstring>
     3 #include <cstdlib>
     4 
     5 namespace DataStructureLib
     6 {
     7 void Exception::init(const char* message,const char* file,int line)
     8 {
     9     m_message=strdup(message);//这里不能直接使用m_message=message,
    10                             //因为message指针指向的数据有可能会在栈、堆、全局区,如果是在栈上,局部变量可能会消失,如果直接使用m_message=message就会不安全    
    11     if(file!=NULL)
    12     {
    13         char sl[16]={0};
    14         itoa(line,sl,10);//将line转为char类型 10代表十进制
    15 
    16         m_location=static_cast<char* >(malloc(strlen(file)+strlen(sl)+2));//加2表示后面的":"和结束符即“/0”
    17         m_location=strcpy(m_location,file);
    18         m_location=strcat(m_location,":");
    19         m_location=strcat(m_location,sl);
    20     }
    21 }
    22 
    23 Exception::    Exception(const char* message)
    24 {
    25     init(message,NULL,0);
    26 }
    27 
    28 Exception::Exception(const char* file,int line)
    29 {
    30     init(NULL,file,line);
    31 }
    32 
    33 Exception::Exception(const char* message,const char* file,int line)
    34 {
    35     init(message,file,line);
    36 }
    37 
    38 Exception::~Exception(void)
    39 {
    40     
    41     free(m_message);
    42     free(m_location);
    43 }
    44 
    45 const char* Exception::message() const
    46 {
    47     return m_message;
    48 }
    49 
    50 const char* Exception::location() const
    51 {
    52     return m_location;
    53 }
    54 
    55 Exception::Exception(const Exception& e)
    56 {
    57     m_message=strdup(e.m_message);
    58     m_location=strdup(e.m_location);
    59 }
    60 
    61 Exception& Exception::operator =(const Exception& e)
    62 {
    63     if (this!=&e)
    64     {
    65         free(m_message);
    66         free(m_location);
    67 
    68         m_message=strdup(e.m_message);
    69         m_location=strdup(e.m_location);
    70     }
    71     return *this;
    72 }
    73 
    74 }

    测试:

    #include<iostream>
    
    #include "SmartPointer.h"
    #include "Exception.h"
    
    using namespace std;
    using namespace DataStructureLib;
    
    int main(int argc,char* argv[])
    {    
        try
        {
            throw(Exception("test",__FILE__,__LINE__));
        }
        catch (const Exception& e)
        {
            cout<<e.message()<<endl;
            cout<<e.location()<<endl;
        }
    
        return 0;
    } 
     

    结果:

  • 相关阅读:
    arcgis10.2 sde配置
    创建只读账号oracle
    oracle 的tnsnames.ora,listener.ora
    gp工具的许可
    复制整个数据库
    显示二维表格的位置计算
    windows文件名格式的中文+数字混合字符串排序
    supergridcontrol记录,分页
    outlook-由于本机的限制,该操作已被取消。请与系统管理员联系。
    自定义单元格式
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/9545684.html
Copyright © 2011-2022 走看看