Pengendalian pengecualian C++


Pengecualian ialah masalah yang berlaku semasa pelaksanaan program. Pengecualian C++ ialah situasi khas yang berlaku semasa program berjalan, seperti percubaan untuk membahagi dengan sifar.

Pengecualian menyediakan cara untuk memindahkan kawalan program. Pengendalian pengecualian C++ melibatkan tiga kata kunci: cuba, tangkap dan lempar.

  • lempar: Apabila masalah berlaku, program akan membuang pengecualian. Ini dilakukan menggunakan kata kunci lempar.

  • tangkap: Tangkap pengecualian melalui pengendali pengecualian pada titik di mana anda ingin menangani masalah itu. Kata kunci tangkap digunakan untuk menangkap pengecualian.

  • cuba: Kod dalam blok cuba mengenal pasti pengecualian khusus yang akan dicetuskan. Ia biasanya diikuti oleh satu atau lebih blok tangkapan.

Jika blok melontar pengecualian, kaedah untuk menangkap pengecualian akan menggunakan kata kunci cuba dan tangkap. Kod yang mungkin membuang pengecualian diletakkan dalam blok cuba Kod dalam blok cuba dipanggil kod perlindungan. Sintaks untuk menggunakan pernyataan try/catch adalah seperti berikut:

try
{
   // 保护代码
}catch( ExceptionName e1 )
{
   // catch 块
}catch( ExceptionName e2 )
{
   // catch 块
}catch( ExceptionName eN )
{
   // catch 块
}

Jika blok try akan membuang pengecualian yang berbeza dalam situasi yang berbeza, anda boleh cuba menyenaraikan berbilang catch pernyataan, digunakan untuk menangkap pelbagai jenis pengecualian.

Throw Exception

Anda boleh membuang pengecualian di mana-mana sahaja dalam blok kod menggunakan pernyataan throw. Operan pernyataan lontaran boleh berupa sebarang ungkapan, dan jenis hasil ungkapan menentukan jenis pengecualian yang dilontar.

Berikut ialah contoh pengecualian yang dilemparkan apabila cuba membahagi dengan sifar:

double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}

pengecualian tangkapan

tangkap blok diikuti dengan cuba blok, digunakan untuk menangkap pengecualian. Anda boleh menentukan jenis pengecualian yang ingin anda tangkap, yang ditentukan oleh pengisytiharan pengecualian dalam kurungan selepas kata kunci tangkapan.

try
{
   // 保护代码
}catch( ExceptionName e )
{
  // 处理 ExceptionName 异常的代码
}

Kod di atas akan menangkap pengecualian jenis ExceptionName. Jika anda mahu blok tangkapan dapat mengendalikan sebarang jenis pengecualian yang dilemparkan oleh blok cuba, anda mesti menggunakan elipsis... di dalam kurungan pengisytiharan pengecualian, seperti ini:

try
{
   // 保护代码
}catch(...)
{
  // 能处理任何异常的代码
}

Berikut ialah contoh , baling Pengecualian bahagi-dengan-sifar dan tangkap pengecualian dalam blok tangkapan.

#include <iostream>
using namespace std;

double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
     z = division(x, y);
     cout << z << endl;
   }catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}

Memandangkan kita melemparkan pengecualian jenis const char*, apabila menangkap pengecualian, kita perlu menggunakan const char* dalam blok tangkapan. Apabila kod di atas disusun dan dilaksanakan, ia akan menghasilkan keputusan berikut:

Division by zero condition!

C++ Standard Exceptions

C++ menyediakan satu siri pengecualian standard, ditakrifkan dalam <exception> ;, kami boleh menggunakan pengecualian standard ini dalam program kami. Mereka disusun dalam hierarki kelas ibu bapa-anak seperti berikut:

cpp_exceptions.jpg

Jadual berikut ialah penerangan bagi setiap pengecualian yang berlaku dalam hierarki di atas:

异常描述
std::exception该异常是所有标准 C++ 异常的父类。
std::bad_alloc该异常可以通过 new 抛出。
std::bad_cast该异常可以通过 dynamic_cast 抛出。
std::bad_exception这在处理 C++ 程序中无法预期的异常时非常有用。
std::bad_typeid该异常可以通过 typeid 抛出。
std::logic_error理论上可以通过读取代码来检测到的异常。
std::domain_error当使用了一个无效的数学域时,会抛出该异常。
std::invalid_argument当使用了无效的参数时,会抛出该异常。
std::length_error当创建了太长的 std::string 时,会抛出该异常。
std::out_of_range该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator[]()。
std::runtime_error理论上不可以通过读取代码来检测到的异常。
std::overflow_error当发生数学上溢时,会抛出该异常。
std::range_error当尝试存储超出范围的值时,会抛出该异常。
std::underflow_error当发生数学下溢时,会抛出该异常。

Tentukan pengecualian baharu

Anda boleh menentukan pengecualian baharu dengan mewarisi dan melebihkan kelas pengecualian. Contoh berikut menunjukkan cara menggunakan kelas std::exception untuk melaksanakan pengecualian anda sendiri:

#include <iostream>
#include <exception>
using namespace std;

struct MyException : public exception
{
  const char * what () const throw ()
  {
    return "C++ Exception";
  }
};
 
int main()
{
  try
  {
    throw MyException();
  }
  catch(MyException& e)
  {
    std::cout << "MyException caught" << std::endl;
    std::cout << e.what() << std::endl;
  }
  catch(std::exception& e)
  {
    //其他的错误
  }
}

Ini akan menghasilkan keputusan berikut:

MyException caught
C++ Exception

Di sini, apa() Merupakan kaedah awam yang disediakan oleh kelas pengecualian, yang telah terlebih beban oleh semua kelas sub-pengecualian. Ini akan mengembalikan sebab pengecualian.