C++编程思想 第2卷 第1章 异常处理 异常规格说明

有时不要求程序提供资料告诉函数的使用者在函数使用时抛出什么异常

异常规则使用了关键字throw,函数可能抛出所有可能异常的类型应该写在
throw之后的括号中

unexpected()函数
如果函数所抛出的异常没有列在异常规格说明的异常集中,一个特殊的函数
unexpected()将会被调用

set_unexpected()函数
像terminate()函数一样,unexpected()可以提供一种机制设置自己的函数来
响应意外的异常

为了使用set_unexpected()函数,编程人员在代码中包含头文件<exception>

//: C01:Unexpected.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Exception specifications & unexpected(),
//{-msc} (Doesn't terminate properly)
#include <exception>
#include <iostream>
using namespace std;

class Up {};
class Fit {};
void g();

void f(int i) throw(Up, Fit) {
  switch(i) {
    case 1: throw Up();
    case 2: throw Fit();
  }
  g();
}

// void g() {}         // Version 1
void g() { throw 47; } // Version 2

void my_unexpected() {
  cout << "unexpected exception thrown" << endl;
  exit(0);
}

int main() {
  set_unexpected(my_unexpected); // (Ignores return value)
  for(int i = 1; i <=3; i++)
    try {
      f(i);
    } catch(Up) {
      cout << "Up caught" << endl;
    } catch(Fit) {
      cout << "Fit caught" << endl;
    }
    getchar();
} ///:~

创建Up类和Fit类作为异常类

函数f()在其异常规格说明中声明仅会抛出Up和Fit类型的异常,但是从函数
的定义来看却不是这样的

按照自定义unexpected()函数的格式要求,my_unexpected()函数没有参数
和返回值

在main()函数中,try块位于for循环的内部,所有可能情况都被执行了。

仅Up和Fit异常能够被捕获,因为函数f()的编写者称只有这两种异常会被
触发

在调用set_unexpected()的时候,函数的返回值被忽略了,如果希望在某个
时刻恢复向前的unexpected(),可将set_unexpected()的返回值保存在一个
指向函数的指针中

如果unexpected处理器所抛出的异常还是不符合函数的异常规格说明,会发生:
如果函数的异常规格说明中包括std::bad_exceptioon,unexpected处理器
所抛出的异常会被替换成std::bad_exceptioon对象,然后,程序恢复到
这个函数被调用的位置重新开始异常匹配

如果函数的异常规格说明中不包括std::bad_exceptioon,程序会调用terminate()
函数

//: C01:BadException.cpp {-bor}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
#include <exception>    // For std::bad_exception
#include <iostream>
#include <cstdio>
using namespace std;

// Exception classes:
class A {};
class B {};

// terminate() handler
void my_thandler() {
  cout << "terminate called" << endl;
  //exit(0);
}

// unexpected() handlers
void my_uhandler1() { throw A(); }
void my_uhandler2() { throw; }

// If we embed this throw statement in f or g,
// the compiler detects the violation and reports
// an error, so we put it in its own function.
void t() { throw B(); }

void f() throw(A) { t(); }
void g() throw(A, bad_exception) { t(); }

int main() {
  set_terminate(my_thandler);
  set_unexpected(my_uhandler1);
  try {
    f();
  } catch(A&) {
    cout << "caught an A from f" << endl;
  }
  set_unexpected(my_uhandler2);
  try {
    g();
  } catch(bad_exception&) {
    cout << "caught a bad_exception from g" << endl;
  }
  try {
    f();
  } catch(...) {
    cout << "This will never print" << endl;
  }
  getchar();
} ///:~

处理器my_uHandler1()抛出一个可以接受的异常(A),所以程序的执行流程
成功地恢复到了第1个catch块中

输出
用命令行
terminate called

用vs 运行
中断一次 运行一次 再中断一次 再运行一次出现
This will never print

或者按两次继续按钮
This will never print
输出
Up caught
Fit caught

出现终止 重试 忽略对话框 

猜你喜欢

转载自blog.csdn.net/eyetired/article/details/81570771