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\n");
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:\n";
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.\n";
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 << "\nNext try block:\n";
58     try
59     {
60         sales2[2] =37.5;
61         sales1[20]=23345;
62         cout<<"End of try block 2.\n";
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\n";
76      return 0;
77 }

 

posted @ 2019-02-26 09:00  Grooovvve  阅读(212)  评论(0)    收藏  举报