Android NDK来发之旅24--C++--异常处理

作者: 香沙小熊 | 来源:发表于2017-11-27 15:04 被阅读103次

Android NDK开发之旅 目录

C++ 异常处理

异常是程序在执行期间产生的问题。C++ 异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。
异常提供了一种转移程序控制权的方式。C++ 异常处理涉及到三个关键字:trycatchthrow

  • throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
  • catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常。
  • try: try 块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个 catch 块。
    如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。使用 try/catch 语句的语法如下所示:
try
{
   // 保护代码
}catch( ExceptionName e1 )
{
   // catch 块
}catch( ExceptionName e2 )
{
   // catch 块
}catch( ExceptionName eN )
{
   // catch 块
}

如果 try 块在不同的情境下会抛出不同的异常,这个时候可以尝试罗列多个 catch 语句,用于捕获不同类型的异常。

示例如下:
#include <iostream>

using namespace std;

//C++ 异常处理,根据抛出的异常数据类型,进入到相应的catch中
void main() {

    //try
    //{
    //  int age = 300;
    //  if (age > 200) {
    //      throw "发生异常";
    //  }
    //  throw 3.3;

    //}
    //catch (int a)
    //{
    //  cout << "int 异常" << endl;
    //}

    //catch (char* b) {
    //  cout << b << endl;
    //}
    ////未知类型
    //catch (...) {
    //  cout << "int 异常" << endl;
    //}


    try
    {
        int age = 300;
        if (age > 200) {
            //抛出未知异常
            throw 3.3; //3.3既不是char*型 也不是int型 
        }
        

    }
    catch (int a)
    {
        cout << "int异常" << endl;
    }

    catch (char* b) {
        cout << b << endl;
    }
    //未知类型
    catch (...) {
        cout << "抛出未知异常" << endl;
    }


    system("pause");
}

结果如下:
抛出未知异常

抛出异常对象

#include <iostream>

using namespace std;

//抛出对象
//异常类
class MyException {
};
void mydiv(int a, int b) {
    if (b==0) {
        //throw MyException();
        //throw new MyException; //抛出异常指针
        throw MyException();
    }
}
void main() {
    try {
        mydiv(8, 0);
    }
    //会产生对象的副本
    //catch (MyException e) {
    //  cout << "MyException" << endl;
    //}

    catch (MyException* e1) {
        cout << "MyException指针" << endl;
        delete e1;
    }
    catch (MyException& e2) {
        cout << "MyException引用" << endl;
    }
    system("pause");
}
结果如下:
MyException引用
注意: MyException 和MyException& 不能同时出现

C++标准的异常

C++ 提供了一系列标准的异常,定义在 <exception> 中,我们可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的,如下所示:

标准的异常

下表是对上面层次结构中出现的每个异常的说明:

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

using namespace std;

void mydiv(int a, int b) {
    if (b > 10) {
        throw out_of_range("out_of_range");
    }
    else if (b == 0) {
        throw invalid_argument("invalid_argument");
    }
}

void main() {
    try
    {
        mydiv(8, 20);
    }
    catch (out_of_range e1)
    {
        cout << e1.what() << endl;
    }
    system("pause");
}

结果如下:
抛出未知异常
out_of_range

定义新的异常

您可以通过继承和重载 exception 类来定义新的异常。下面的实例演示了如何使用 exception 类来实现自己的异常。

示例如下:
#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)
    {
        cout << "MyException caught" << endl;
        cout << e.what() << endl;
    }
    catch (std::exception& e)
    {
        //其他的错误
    }
    system("pause");
}

结果如下:

MyException caught
C++ Exception

const throw() 不是函数,这个东西叫异常规格说明,表示 what 函数可以抛出异常的类型,类型说明放到 () 里,这里面没有类型,就是声明这个函数不抛出异常,通常函数不写后面的就表示函数可以抛出任何类型的异常。

异常规格说明
1、异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。

可以在函数的声明中列出这个函数可能抛掷的所有异常类型。例如:

void fun() throw(A,B,C,D);
2、若无异常接口声明,则此函数可以抛掷任何类型的异常。
3、不抛掷任何类型异常的函数声明如下:
#include <iostream>
#include <exception>
using namespace std;

class MyException
{
public:
    MyException(const char *message)
        : message_(message)
    {
        cout << "MyException ..." << endl;
    }
    MyException(const MyException &other) : message_(other.message_)
    {
        cout << "Copy MyException ..." << endl;
    }
    virtual ~MyException()
    {
        cout << "~MyException ..." << endl;
    }

    const char *what() const
    {
        return message_.c_str();
    }
private:
    string message_;
};

class MyExceptionD : public MyException
{
public:
    MyExceptionD(const char *message)
        : MyException(message)
    {
        cout << "MyExceptionD ..." << endl;
    }
    MyExceptionD(const MyExceptionD &other)
        : MyException(other)
    {
        cout << "Copy MyExceptionD ..." << endl;
    }
    ~MyExceptionD()
    {
        cout << "~MyExceptionD ..." << endl;
    }
};

void fun(int n) throw (int, MyException, MyExceptionD)
{
    if (n == 1)
    {
        throw 1;
    }
    else if (n == 2)
    {
        throw MyException("test Exception");
    }
    else if (n == 3)
    {
        throw MyExceptionD("test ExceptionD");
    }

}

void fun2() throw()
{

}

int main(void)
{
    try
    {
        fun(2);
    }

    catch (int n)
    {
        cout << "catch int ..." << endl;
        cout << "n=" << n << endl;
    }
    catch (MyExceptionD &e)
    {
        cout << "catch MyExceptionD ..." << endl;
        cout << e.what() << endl;
    }
    catch (MyException &e)
    {
        cout << "catch MyException ..." << endl;
        cout << e.what() << endl;
    }
    system("pause");
    return 0;
}


结果如下:
MyException ...
catch MyException ...
test Exception
~MyException ...

外部类异常

示例如下:
#include <iostream>

using namespace std;

//外部类异常
class Err
{
public:
    class MyException {
    public:MyException() {

        cout << "Division can't be zero !" << endl;
    }
    };

};
void mydiv(int a, int b) {
    if (b ==0) {
        throw Err::MyException();
    }
}

int main()
{
    try
    {
        mydiv(10, 0);
    }
    catch (Err::MyException e)
    {
        cout << "MyException caught" << endl;

    }

    system("pause");
}


结果如下:
Division can't be zero !
MyException caught

特别感谢:
菜鸟C++ 教程






微信号kpioneer

相关文章

网友评论

    本文标题:Android NDK来发之旅24--C++--异常处理

    本文链接:https://www.haomeiwen.com/subject/fcurbxtx.html