• C++_异常8-异常、类和基础


    异常、类和继承以三种方式相互关联。

    首先,可以像标准C++库所做的那样,从一个异常类派生出另一个。

    其次,可以在类定义中嵌套异常类声明来组合异常。

    第三,这种嵌套声明本身可以被继承,还可以作为基类。

     

    接下来用一个例子进行相关的探索;

    以下这个头文件声明了一个Sales类,它用于存储一个年份以及一个包含12个月销售数据的数组。

    LabelledSales类是从Sales派生而来的。新增了一个用于存储数据标签的成员。

     1 //sales.h  -- exception and inheritance
     2 #include <stdexcept>
     3 #include <string>
     4 
     5 class Sales
     6 {
     7 public:
     8     enum {MONTHS = 12};
     9     class bad_index : public std::logic_error
    10     {
    11 
    12     };
    13     explicit Sales(int yy = 0);
    14     Sales(int yy, const double * gr, int n);
    15     virtual ~Sales() {}
    16     int Year() const { return year;}
    17     virtual double operator[] (int i) const;
    18     virtual double & operator[] (int i);
    19 
    20 private:
    21     double gross[MONTHS];
    22     int year;
    23 };
    24 
    25 
    26 class LabeledSales : public Sales
    27 {
    28 public:
    29     class nbad_index : public Sales::bad_index
    30     {
    31     private:
    32         std::string lbl;
    33     public:
    34         nbad_index(const std::string & lb, int ix, const std::string & s = "Index error in LabeledSales object
    ");
    35         const std::string & label_val() const {return lbl;}
    36         virtual ~nbad_index() throw() {}
    37     }
    38     explicit LabeledSales(const std::string & lb = "none", int yy = 0);
    39     LabeledSales(const std::string & lb, int yy, const double * gr, int n);
    40     virtual ~LabeledSales() {}
    41     const std::string & Label() const {return label;}
    42     virtual double operator[] (int i) const;
    43     virtual double & operator[] (int i);
    44 
    45 private:
    46     std::string label;
    47 
    48 };

    分析以下头文件的细节;首先,符号常量位于Sales类的保护部分,这使得派生类能够使用这个值。

    接下来,bad_index被嵌套在Sales类的公有部分中,这使得客户类的catch块可以使用这个类作为类型。

    注意,在外部使用这个类型时,需要使用Sales::bad_index来标识。这个类是从logic_error类派生而来的,能够存储和报告数组索引的超界值。

    nbad_index类被嵌套到LabeledSales的公有部分,这使得客户类可以通过LabeledSales::nbad_index来使用它。

    它是从bad_inde类派生而来的,因此nbad_index归根结底也是从logic_error派生而来的。

    这两个类都有重载的operator[]()方法,这些方法用于访问存储在对象中的数组元素,并在索引超界时引发异常。

     

    接下来是源文件,是没有声明为内联的方法的实现。

     1 //sales.cpp  --Sales implementation
     2 #include "sales.h"
     3 using std::string;
     4 
     5 
     6 Sales::bad_index::bad_index(int ix, const string & s)
     7 : std::logic_error(s), bi(ix)
     8 {
     9 
    10 }
    11 
    12 Sales::Sales(int yy)
    13 {
    14     year = yy;
    15     for(int i = 0; i < Months; ++i)
    16         gross[i] = 0;
    17 }
    18 
    19 Sales::Sales(int yy, const double * gr, int n)
    20 {
    21     year = yy;
    22     int lim = (n< MONTHS)? n : MONTHS;
    23     int i;
    24     for (i=0;i<MONTHS;++i)
    25         gross[i] = gr[i];
    26     // for i >n and i <MONTHS
    27     for (;i < MONTHS;++i)
    28         gross[i] = 0;
    29 }
    30 
    31 double Sales::operator[](int i) const
    32 {
    33     if(i<0 || i>=MONTHS)
    34         throw bad_index(i);
    35     return gross[i];
    36 }
    37 
    38 double & Sales:;operator[] (int i)
    39 {
    40     if(i<0 || i>=MONTHS)
    41         throw bad_index(i);
    42     return gross[i];
    43 }
    44 
    45 LabeledSales::nbad_index::nbad_index(const string & lb, int ix, const string & s):Sales::bad_index(ix,s)
    46 {
    47     lbl =lb;
    48 }
    49 
    50 LabeledSales::LabeledSales(const string & lb, int yy):Sales(yy)
    51 {
    52     label=lb;
    53 }
    54 
    55 LabeledSales::LabeledSales(const string & lb, int yy, const double * gr, int n):Sales(yy, gr, n)
    56 {
    57     label = lb;
    58 }
    59 
    60 double LabeledSales::operator[](int i) const
    61 {
    62     if(i<0 || i>=MONTHS)
    63         throw nbad_index(Label(), i);
    64     return Sales::operator[](i);
    65 }
    66 
    67 double & LabeledSales::operator[](int i)
    68 {
    69     if(i<0 || i>=MONTHS)
    70         throw nbad_index(Label(), i);
    71     return Sales::operator[](i);
    72 }

     接下来编写程序运行一下:

     1 //use_sale.cpp  --nested exceptions
     2 #include <iostream>
     3 #include "sales.h"
     4 
     5 int main()
     6 {
     7     using std::cout;
     8     using std::cin;
     9     using std::endl;
    10 
    11 double vals1[12] =
    12 {
    13     1220, 1100, 1122, 2212, 1232, 2334,
    14     2884, 2393, 3302, 2922, 3002, 3544
    15 };
    16 
    17 double vals[12] =
    18 {
    19     12,11,22,21,32,34,
    20     28,29,33,29,32,35
    21 };
    22 
    23 Sales sales1 ();
    24 LabeledSales sales2();
    25 
    26 cout<<"First try block:
    ";
    27 try
    28 {
    29     int i;
    30     cout<<"Year = "<< sales1.Year() << endl;
    31     for (i =0; i<12; ++i)
    32     {
    33         cout<<sales1[i]<<' ';
    34         if (i % 6 == 5)
    35             cout<<endl;
    36     }
    37     cout<<"Year = "<<sales2.Year()<<endl;
    38     cout<<"Label = "<<sales2.Label()<<endl;
    39     for (i = 0; i<=12; ++i)
    40     {
    41         cout<<sales2[i]<<' ';
    42         if (i % 6 == 5)
    43             cout<<endl;
    44     }
    45     cout<<"End of try block 1.
    ";
    46 }
    47 catch(LabeledSales::nbad_index & bad)
    48 {
    49     cout<<bad.what();
    50     cout<<"Company: "<<bad.label_val()<<endl;
    51     cout<<"bad index: "<<bad.bi_val()<<endl;
    52 }
    53 catch(Sales::bad_index & bad)
    54 {
    55     cout<<bad.what();
    56     cout<<"bad index: "<<bad.bi_val()<<endl;
    57     cout << "
    Next try block:
    ";
    58     try
    59     {
    60         sales2[2] =37.5;
    61         sales1[20]=23345;
    62         cout<<"End of try block 2.
    ";
    63     }
    64     catch(LabeledSales::nbad_index & bad)
    65     {
    66         cout << bad.what();
    67         cout << "Company:" <<bad.label_val()<<endl;
    68         cout << "bad index:" << bad.bi_val() << endl;
    69      }
    70     catch(Sales::bad_index & bad)
    71     {
    72         cout << bad.what();
    73         cout << "bad.bi_val()"<<endl;
    74      }
    75      cout << "done
    ";
    76      return 0;
    77 }
  • 相关阅读:
    C语言实现数据结构中的顺序栈
    什么是A股什么是B股,为什么有AB股之分?
    C语言实现数据结构中的链队列
    C语言实现数据结构中的循环链表
    C语言实现数据结构的链表
    C语言中指针变量作为函数参数和一般变量作为函数参数的区别
    javascrip实现下拉框联动
    C语言实现数据结构中的顺序表
    C语言实现数据结构中的链栈
    SQL语句之基础增删改查 time
  • 原文地址:https://www.cnblogs.com/grooovvve/p/10435128.html
Copyright © 2020-2023  润新知