C++:6.3异常处理

66人阅读 评论(0) 收藏 举报
(努力敲...)
(兴奋...)
 是否保存?

(思考ing)

 ?????

1、C++异常处理入门(try和catch)


   编译器能够保证代码的语法是正确的,但是对逻辑错误和运行时错误却无能为力,例如除数为 0、内存分配失败、数组越界等。这些错误如果放任不管,系统就会执行默认的操作,终止程序运行,也就是我们常说的程序崩溃(Crash)。




    string str = "c plus plus";
    char ch1 = str[100];  //下标越界,ch1为垃圾值
    cout<<ch1<<endl;
    char ch2 = str.at(100);  //下标越界,抛出异常
    cout<<ch2<<endl;


    at() 是 string 类的一个成员函数,它会根据下标来返回字符串的一个字符。与“[ ]”不同,at() 会检查下标是否越界,如果越界就抛出一个异常(错误);而“[ ]”不做检查,不管下标是多少都会照常访问。


    在C++中,我们可以捕获上面的异常,避免程序崩溃。捕获异常的语法为:
try{
    // 可能抛出异常的语句
}catch(异常类型){
    // 处理异常的语句
}


2、
异常既然是一份数据,那么就应该有数据类型。C++规定,异常类型可以是基本类型,也可以是标准库中类的类型,还可以是自定义类的类型。C++语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的类型。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。


异常被捕获后,会和 catch 所能处理的类型对比,如果正好和 catch 类型匹配,或者是它的子类,那么就交给当前 catch 块处理。catch 后面的括号中给出的类型就是它所能处理的异常类型。上面例子中,catch 所能处理的异常类型是 exception,at() 函数抛出的类型是 out_of_range,out_of_range 是 exception 的子类,所以就交给这个 catch 块处理。


catch 后面的exception e可以分为两部分:exception 为异常类型,e 为 exception 类的对象。异常抛出时,系统会创建 out_of_range 对象,然后将该对象作为“实参”,像函数一样传递给“形参”e,这样,在 catch 块中就可以使用 e 了。


3、
  一个 try 后面可以跟多个 catch,异常被捕获时,先和 exception_type_1 作比较,如果异常类型是 exception_type_1 或其子类,那么执行当前 catch 中的代码;如果不是,再和 exception_type_2 作比较……依此类推,直到 exception_type_n。如果最终也没有找到匹配的类型,就只能交给系统处理,终止程序。






4、throw:抛出自己的异常


throw 是C++中的关键字,用来抛出异常。如果不使用 throw 关键字,try 就什么也捕获不到;上节提到的 at() 函数在内部也使用了 throw 关键字来抛出异常。


throw 既可以用在标准库中,也可以用在自定义的函数中,抛出我们期望的异常。throw 关键字语法为:


 
throw exceptionData;




exceptionData 是“异常数据”的意思,它既可以是一个普通变量,也可以是一个对象,只要能在 catch 中匹配就可以。


5、exception类






C++语言本身或者标准库抛出的异常都是 exception 的子类,称为标准异常(Standard Exception)。你可以通过下面的语句来匹配所有标准异常:
try{
    //可能抛出异常的语句
}catch(exception &e){
    //处理异常的语句
}
之所以使用引用,是为了提高效率。如果不使用引用,就要经历一次对象拷贝(拷贝对象时要调用拷贝构造函数)的过程。




6、 exception 类的直接派生类




logic_error 逻辑错误。


runtime_error 运行时错误。


bad_alloc 使用 new 或 new[ ] 分配内存失败时抛出的异常。


bad_typeid 使用 typeid 操作一个 NULL 指针,而且该指针是带有虚函数的类,这时抛出 bad_typeid 异常。


bad_cast 使用 dynamic_cast 转换失败时抛出的异常。


ios_base::failure io 过程中出现的异常。


bad_exception 这是个特殊的异常,如果函数的异常列表里声明了bad_exception 异常,当函数内部抛出了异常列表中没有的异常时,如果调用的 unexpected() 函数中抛出了异常,不论什么类型,都会被替换为 bad_exception 类型。


7、logic_error 的派生类 




   异常名称 说  明


length_error 试图生成一个超出该类型最大长度的对象时抛出该异常,例如 vector 的 resize 操作。


domain_error 参数的值域错误,主要用在数学函数中,例如使用一个负值调用只能操作非负数的函数。


out_of_range 超出有效范围。


invalid_argument 参数不合适。在标准库中,当利用string对象构造 bitset 时,而 string 中的字符不是 ’0’ 或 ’1’ 的时候,抛出该异常。




8、runtime_error 的派生类 


   range_error        计算结果超出了有意义的值域范围。


   overflow_error 算术计算上溢。


   underflow_error 算术计算下溢。
----------------------------------------------


#include <cstdio>
#include <cstdlib>
#include <exception>
#include <string>


class myexception : public std::exception {
public:
myexception(std::string s) : exception(s.c_str()) {


}
virtual ~myexception() {
printf("myexception's destructor\n");
}
virtual const char *what() const {
return exception::what();
}
public:
std::string _s;
};


class A {
public:
~A() {
printf("A's destructor\n");
}


};


class B {
public:
~B() {
printf("B's destructor\n");
}


};


void Func() {
A a;
printf("dasd\n");
myexception e("p is NULL");
e._s = "haha";
try{
int *p = NULL;
if (p == NULL) {
throw e;
}
}
catch (myexception &e) {
e._s = "heiheihei";
printf("%s\n", e.what());
throw;
}


printf("%s\n", e._s.c_str());


B b;
}


void Func2() {
try {
Func();
}
catch (myexception &e) {
printf("Func2 : %s\n", e._s.c_str());
throw;
}
}


int main() {
try {
Func2();
}
catch (myexception &e) {
printf("main: %s\n", e._s.c_str());
}
printf("hahah\n");


system("PAUSE");
return 0;
}


这个函数输出为:


dasd
p is NULL
myexception's destructor
A's destructor
Func2 : heiheihei
main: heiheihei
myexception's destructor
hahah


函数说明:
  
  main函数起,调用fun2(),进入fun2(),调用fun(),进入fun()后,   先创建一个A类对象a,
  ★输出dasd;
  再创建一个异常并初始化e(p is NULL),然后给_s赋值haha ;
  扔异常,在fun()的catch中接到,类型匹配,重新给_s赋值heiheihei;
  ★输出what,也就是“p is NULL”;
  扔异常,fun()里面没得接,要回到函数调用处,也就是fun2();
  回之前,要把局部变量销毁,也就是a 和 e;----------因为局部变量在栈区,所以先销毁e,在销毁a。(先来后出)所以输出★
  myexception's destructor
  A's destructor
  回到fun2();类型匹配,有得接,★打印_s---heiheihei;
  再扔,回到main 。因为在fun2()是直接引用的异常,所以不会销毁,也就不会析构。
   类型匹配,有得接,打印heiheihei,不扔了,后面没有catch接了,交给系统处理,终止程序。析构。★打印myexception's destructor
  ★打印hahaha,



























查看评论

PHP4 + MYSQL + APACHE 在 WIN 系统下的安装、配置

I、配置之前的工作 配置之前,但是是去找个合适的地方下载。现在,PHP已经发展到PHP4了,所以,我只是将PHP4的安装配置介绍给大家,其实PHP3的配置和PHP4是差不多的。另外,考虑到我本人用Li...
  • leejd
  • leejd
  • 2000-12-28 21:11:00
  • 2165

C++ 异常处理 C++ 异常处理

  • 2011年07月18日 11:10
  • 818KB
  • 下载

C++异常处理机制总结

参考文档:《C++编程思想》《C++Primer》《More effective C++》 一、             传统的错误处理机制: 1.         返回值或全局错误状态标志。缺点:需...
  • MulinB
  • MulinB
  • 2007-08-29 10:07:00
  • 2360

C++异常处理基本思想

1)C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层调用者可以再适当的位置设计对不同类型异常的处理。 2)异常是专...
  • zyq522376829
  • zyq522376829
  • 2015-07-06 16:15:25
  • 1304

JAVA异常处理 与C++的不同

*Java异常处理模型   对于一个非常熟悉 C++ 异常处理模型的程序员来说,它几乎可以不经任何其它培训和学习,就可以完全接受和能够轻松地使用 Java 语言中的异常处理编程方法。这是因为 Java...
  • ljlove2008
  • ljlove2008
  • 2008-10-14 23:32:00
  • 2552

C++中的异常处理机制以及异常规范

以下代码运行环境为64位系统下的VS2013 C++中的异常情况: 语法错误(编译错误):比如变量未定义、括号不匹配、关键字拼写错误等等编译器在编译时能发现的错误,这类错误可以及时被编译器发现...
  • scmuzi18
  • scmuzi18
  • 2017-04-04 18:10:37
  • 712

C++异常处理实例

/************************************************************************************************ *...
  • JarvisChu
  • JarvisChu
  • 2011-07-22 22:41:51
  • 4101

C++与Java异常处理的区别

异常的捕获 1) Java中的异常捕获 在Java中异常捕获有以下几种方法: 1.1        try…catch…块   用try来设定一段能够预防所有异常的程序。紧跟在try后面,可以...
  • yahohi
  • yahohi
  • 2012-02-04 15:40:31
  • 2746

C++中异常处理与if判断的问题

异常情况也就是对情况是否异常做出的判断,那么异常处理和if判断语句有什么区别呢?各有什么好处? if-else 方式的好处在于更贴近与逻辑思维,性能优于Exception。相对于Except...
  • tinyway
  • tinyway
  • 2014-01-09 11:10:43
  • 443

【VS开发】C++异常处理操作

异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制。 也许我们已经使用过异常,但是你会是一种习惯吗,不要老是想着当我打开一个文件的时候才用异常判断一下,我知道对你来说你喜欢...
  • LG1259156776
  • LG1259156776
  • 2016-05-21 21:34:49
  • 1886
    个人资料
    等级:
    访问量: 950
    积分: 239
    排名: 31万+
    文章分类
    文章存档
    最新评论