C++异常介绍

目录

一.异常

1.1C++异常概念

1.2异常的使用

1.3异常和栈帧,重新抛出

二.异常体系

2.1自定义异常体系

 2.2C++标准库的异常体系

2.3异常规范

3.异常的优缺点

3.1优点

 3.2缺点


一.异常

1.1C++异常概念

语言传统的处理错误的方式:
1. 终止程序,如 assert ,缺陷:用户难以接受。如发生内存错误,除 0 错误时就会终止程序。
2. 返回错误码
异常是一种处理错误的方式, 当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的
直接或间接的调用者处理这个错误
throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
catch: 在您想要处理问题的地方,通过异常处理程序捕获异常 . catch 关键字用于捕获异
常,可以有多个 catch 进行捕获。
try: try 块中的代码标识将被激活的特定异常 , 它后面通常跟着一个或多个 catch 块。

1.2异常的使用

异常的抛出和匹配原则
1. 异常是通过 抛出对象而引发 的,该 对象的类型 决定了应该激活哪个 catch 的处理代码。
2. 选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,
所以会生成一个拷贝对象,这个拷贝的临时对象会在被 catch 以后销毁。(这里的处理类似
于函数的传值返回)
4. catch(...) 可以捕获任意类型的异常,问题是不知道异常错误是什么。
例如:
double Division(int a, int b)
{
    // 当b == 0时抛出异常
    if (b == 0)
        throw "Division by zero condition!";
    else
        return ((double)a / (double)b);
}
void Func()
{
    int a, b;
    cin >> a >> b;
    cout << Division(a,b) << endl;
}
int main()
{
    try
    {
        Func();
    }
    catch (const char* errmsg)
    {
        cout << errmsg << endl;
    }
    catch (...)
    {
        cout << "unkown exception" << endl;
    }
    return 0;
}

当发生除零错误时会被抛出,被catch捕获,catch(...)可以捕获任意类型的异常,但会优先去匹配最适合的。

1.3异常和栈帧,重新抛出

如图

C++异常介绍_第1张图片

 也就是要去匹配最适合的catch语句。

有可能单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用 链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。

例如:(例子不是很恰当)

double Division(int a, int b)
{
    // 当b == 0时抛出异常
    if (b == 0)
        throw "Division by zero condition!";
    else
        return ((double)a / (double)b);
}
void Func()
{
    int a, b;
    cin >> a >> b;
    cout << Division(a,b) << endl;
}
void show()
{
    int* arr = new int[10];
    Func();
    delete[] arr;
}
int main()
{
    try
    {
        show();
    }
    catch (const char* errmsg)
    {
        cout << errmsg << endl;
    }
    catch (...)
    {
        cout << "unkown exception" << endl;
    }
    return 0;
}

当发生除零错误时,通过throw直接跳到catch语句后,往后执行,而show()函数内new 出来的空间未释放。

解决办法:

void show()
{
    int* arr = new int[10];
    try {
        Func();//若Func函数出现异常,将前面的arr释放
   }
    catch (...)
    {
        delete[]arr;
        throw;    //重新抛出
    }
    delete[] arr;
}

二.异常体系

2.1自定义异常体系

可以定义一套继承的规范异常体系,抛出继承的派生类,捕获一个基类即可。

例如:

定义一个父类,两个子类。发生异常,抛出子类,在子类中填充错误信息,用父类接受,通过多态实现,打印错误信息。

class A
{
public:
	A(const string str, int id)
		:str_(str)
		,id_(id)
	{}
	virtual string what() const
	{
		return str_;
	}
	string str_;
	int id_;
};

class Aa : public A
{
public:
	Aa(string str,int id,string stra)
		:stra_(stra)
		,A(str,id)
	{}
	virtual string what() const
	{
		string Str("Aa");
		Str += stra_;
		return Str;
	}
private:
	string stra_;
};

class Ab :public A
{
public:
	Ab(string str, int id, string strb)
		:strb_(strb)
		,A(str,id)
	{}
	virtual string what() const
	{
		string Str("Ab");
		Str += strb_;
		return Str;
	}
private:
	string strb_;
};

void AAA()
{
	//若发生错误
	throw Aa("AAA", 8, "AAAA");
}

void BBB()
{
	//若发生错误
	throw Ab("BBB", 9, "BBBB");
}
void show()
{
	AAA();
	BBB();
}
int main()
{
	try {
		show();
	}
	catch (A& a)
	{
		cout << a.what() << endl;
	}
	return 0;
}

结果:

 2.2C++标准库的异常体系

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

C++异常介绍_第2张图片

① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、和赋值操作符重载。

② logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述

③ 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息。

对异常的一写说明:

C++异常介绍_第3张图片

 

简单看个例子:

C++异常介绍_第4张图片

 

2.3异常规范

1.在函数后加上throw(类型A,类型B)可以列出这个函数能抛出的所有异常类型

void test() throw(string,vector);

2,如果只跟一个类型,代表该函数只会抛出一种类型的异常

void* operator new(size_t size) throw (std::bad_alloc);

3.如果跟的是throw()代表这个函数不会抛出异常

void* test(size_t sz, void* p) throw();

4.noexcept来标识不会抛出异常

void* test(size_t sz, void* p) noexcept;

例如:

C++异常介绍_第5张图片

 

3.异常的优缺点

3.1优点

1.将异常对象定义好后,相比错误码的方式可以清晰准确的展示出错误的各种信息,更加直观。

2.传统返回错误码的方式去返回错误码时,需要层层返回。

3.很多的第三方库都包含异常,比如boost、gtest等等常用的库,那么我们使用它们时也需要使用异常。

4. 部分函数使用异常更好处理,比如构造函数没有返回值,不方便使用错误码方式处理。比如 T& operator这样的函数,如果pos越界了只能使用异常或者终止程序处理,没办法通过返回 值表示错误。

 3.2缺点

1.异常的执行流跳动比较大,有时可能很难追踪错误。

2.C++没有垃圾回收机制,异常非常容易导致内存泄漏、死锁等异常安全问题。(使用RAII来处理资源的管理问题)。

3.异常需要规范去使用,依赖用户的规范,习惯。

你可能感兴趣的:(C++入门学习,开发语言,c++)