double future_value(double initial_balance, double p, int n)cout << future_value(1000, -100, -1);
{ double b = initial_balance * pow(1 + p / 100, n);
return b;
}
double future_value(double initial_balance, double p, int n)** Проверяват се условията за грешка, не се прави нищо в случай на грешка (връща се фалшива стойност).
{ return initial_balance * pow(1 + p / 100, n);
}
double future_value(double initial_balance, double p, int n)** Проверяват се условията за грешка, съобщава се за грешката и се спира изпълнението на програмата.
{ if (p < 0 || n < 0) return 0;
return initial_balance * pow(1 + p / 100, n);
}
double future_value(double initial_balance, double p, int n)Въникващи проблеми:
{ assert(p >= 0 && n >= 0);
return initial_balance * pow(1 + p / 100, n);
}
double future_value(double initial_balance, double p, int n)Може да не се задава име на обекта за обработка на изключения:
{ if (p < 0 || n < 0)
{ logic_error description("illegal future_value parameter");
throw description; // изхвърля изключението description
}
return initial_balance * pow(1 + p / 100, n);
}
double future_value(double initial_balance, double p, int n)logic_error е стандартен клас за изключения, който е дефиниран в заглавния файл stdexcept.
{ if (p < 0 || n < 0)
throw logic_error("illegal future_value parameter");
return initial_balance * pow(1 + p / 100, n);
}
tryАко някоя от функциите в блока try изхвърли изключение от тип logic_error, или вика друга функция, която изхвърля такова изключение, блокът на catch(logic_error) се изпълнява веднага.
{
// code
}
catch (logic_error& e)
{
// handler
}
while (more)Член-функцията what от класа logic_error връща низа, който е зададен като параметър при конструиране на обекта в оператора throw.
{ try
{
// code
}
catch (logic_error& e)
{ cout << "A logic error has occurred "
<< e.what() << "\n";
........
}
}
| try 
 | 
#include <cmath>
            
           using namespace std;
          
          double future_value(double initial_balance, double
          p, int n)
          { 
                if (p < 0
          || n < 0)
              { logic_error description("illegal future_value parameter");
                  throw description;
              }
              return initial_balance * pow(1 + p / 100,
          n);
          }
          
          int main()
          { 
              bool more = true;
              while (more)
              { 
                    double init,
          interest;
                  int years;
                  cout << "Enter initial value, interest and years: ";
                  cin >> init
          >> interest >> years;
          
                  try 
                  { 
                      double
          fvalue = future_value(init, interest, years); 
                      cout
          << "The future value is " <<
          fvalue << endl; 
                  }
                  catch (logic_error&
          e)
                      { 
                     
              cout << "A
            logic error has occurred " << e.what() <<
          "\n";
                      } 
                      cout
          << "Retry? (y/n)";
                  char input;
                  cin >> input;
                  if (input ==
          'n') more = false;
          } 
               return
          0;
          }
        
    | nkirov@cpp % c++ exception1.cpp | 
class FutureValueError : public logic_error {Функцията future_value може да изхвърли FutureValueError обект:
public:
FutureValueError(const char reason[]);
};
FutureValueError::FutureValueError(const char reason[])
: logic_error(reason){}
if (p < 0 || n < 0)Тъй като FutureValueError е logic_error (наследяване), то това изключение може да се прихване от catch(logic_error& e).
throw FutureValueError("illegal parameter");
tryВ този случай ще се изпълни само първия catch блок.
{
// code
}
catch (FutureValueError& e)
{
// handler1
}
catch (logic_error& e)
{
// handler2
}
// exception2.cpp
#include <iostream>
#include <stdexcept>#include<cmath>using namespace std;
class FutureValueError : public logic_error {
public:
FutureValueError(const char reason[]);
};
FutureValueError::FutureValueError(const char reason[])
: logic_error(reason){}
double future_value(double initial_balance, double p, int n)
{ if (p < 0 || n < 0)
throw FutureValueError("illegal future_value parameter");
return initial_balance * pow(1 + p / 100, n);
}
void read(double& init, double& interest, int& years)
{ cout << "Enter initial value, interest and years: ";
cin >> init >> interest >> years;
if (years > 100) throw logic_error("too many years!");
cout << init << " " << interest << " " << years << endl;
}
int main()
{ bool more = true;
while (more)
{ double init, interest;
int years;
try
{ read(init, interest, years);
double fvalue = future_value(init, interest, years);
cout << "The future value is " << fvalue << endl;
}
/**/
catch (FutureValueError& e)
{ cout << "A FutureValueError has occurred: "
<< e.what() << "\n";
}
/**/
catch (logic_error& e)
{ cout << "A logic error has occurred: "
<< e.what() << "\n";
}
cout << "Retry? (y/n)";
char input;
cin >> input;
if (input == 'n') more = false;
}
return 0;
}
| nkirov@cpp
                  % c++ exception2.cpp | 
bool Product::read(fstream& fs)Когато възникне логическа грешка, няма смисъл да се повтори същата операция, но при runtime_error има шанс да се повтори операцията и грешката да се избегне.
{ getline(fs, name);
if (name == "") return false; // end of file
fs >> price >> score;
if (fs.fail())
throw runtime_error("Error while reading product");
string remainder;
getline(fs, remainder);
return true;
}

void process_products(fstream& fs)Когато функцията read изхвърли изключение, функцията process_products прекъсва и механизмът за обработка на изключения търси подходящ catch блок.
{ vector<Product> products;
bool more = true;
while (more)
{ Product p;
if (p.read(fs)) products.push_back(p);
else more = false;
}
// do something with products
}
Product* p = new Product();Този код генерира "memory leak", ако функцията read изхвърли изключение (виж product1.cpp).
if (p->read())
{
...
}
delete p; // never executes if read throws an exception
Product* p = NULL;Блокът catch(...) обработва всяко изключение, а операторът throw без обект изпраща изключението да се обработва от друг catch блок.
try
{ p = new Product();
if (p->read())
{
...
}
delete p;
}
catch(...)
{ delete p;
throw;
}
| nkirov@cpp % c++
                product2.cpp nkirov@Kcpp % ./a.out Product: ABC 1000 20 Product: ZDR 2000 AA 1. Error while reading product 2. Error while reading product nkirov@cpp % | 
void process_products(fstream& fs)означава, че само зададените две изключения са позволени на тази функция.
throw (UnexpectedEndOfFile, bad_alloc)
void process_products(fstream& fs)задава забрана за всички изключения, а липса на throw означава разрешение за изключения от всеки тип.
throw ()
| ff1 f 2. 22 | 
| nkirov@cpp % c++
                strous.cpp nkirov@cpp % ./a.out begin main() begin f() use_vectors() Vector::Vector ERROR in the constructor Vector::Size nkirov@cpp % |