当前位置:网站首页>unusual understanding

unusual understanding

2022-08-10 22:01:00 GracefulBlack

CThe language tradition handles errors

  • 返回错误码 , 缺陷:An error number is returned,Don't know which error is,很难受,Also need to check the error code table
  • 终止程序,比如assert,缺陷:有点太激进了,It crashes immediately after encountering an error
    在这里插入图片描述

C++异常

概念

在这里插入图片描述

用法

  • catchThe code is not executed sequentially,没有异常的情况,catchThe code is skipped directly
  • 代码出现异常时,Code is not executed sequentially,will jump right to where it was caught
    在这里插入图片描述
#include<iostream>
#include<string>
#include<time.h>
#include <thread>
#include <vector>
using namespace std;

double Division(int a, int b)
{
    
	// 当b == 0时抛出异常
	if (b == 0)
		throw "Division by zero condition!";
	else
		return ((double)a / (double)b);
}

void Func1()
{
    
	try
	{
    
		int len, time;
		cin >> len >> time;
		cout << Division(len, time) << endl;
	}
	catch (int errid)
	{
    
		cout << errid << endl;
	}
}

void Func2()
{
    
	int len, time;
	cin >> len >> time;
	if (time != 0)
	{
    
		throw 1;
	}
	else
	{
    
		cout << len << " " << time << endl;
	}
}

int main()
{
    
	try 
	{
    
		Func1();
		Func2();
	}
	catch (const char* errmsg)
	{
    
		cout << errmsg << endl;
	}
	catch (int errid) 
	{
    
		cout << errid << endl;
	}
	catch (...)
	{
    
		cout << "unkown exception" << endl;
	}

	return 0;
}
  • If an exception object is thrown,What is thrown is a copy of the exception object,Because this object may be generated temporarily,The copied temporary object will be therecatch以后销毁
double Division(int a, int b)
{
    
	// 当b == 0时抛出异常
	if (b == 0)
	{
    
		string str("除零错误");
		throw str;
	}
	else
	{
    
		return ((double)a / (double)b);
	}
}

void Func1()
{
    
	int len, time;
	cin >> len >> time;
	cout << Division(len, time) << endl;
}

int main()
{
    
	try
	{
    
		Func1();
	}
	catch (const string& errmsg)
	{
    
		cout << errmsg << endl;
	}

	return 0;
}

  • If the thrown exception is not caught,那么程序就会被终止
  • catch(…)means to capture any type
    在这里插入图片描述
  • Below after being capturedfunc2会继续执行 , catchSubsequent clauses will continue to execute
double Division(int a, int b)
{
    
	// 当b == 0时抛出异常
	if (b == 0)
	{
    
		string str("除零错误");
		throw str;
	}
	else
	{
    
		return ((double)a / (double)b);
	}
}

void Func2()
{
    
	int len, time;
	cin >> len >> time;
	if (time != 0)
	{
    
		throw 3.33;
	}
	else
	{
    
		cout << len << " " << time << endl;
	}
}

void Func1()
{
    
	try
	{
    
		int len, time;
		cin >> len >> time;
		cout << Division(len, time) << endl;
	}
	catch (const string& errmsg)
	{
    
		cout << errmsg << endl;
	}


	Func2();
}



int main()
{
    
	try
	{
    
		Func1();
	}
	catch (const string& errmsg)
	{
    
		cout << errmsg << endl;
	}
	catch (int errid)
	{
    
		cout << errid << endl;
	}
	catch (...)
	{
    
		cout << "未知异常" << endl;
	}

	return 0;
}

代码二

double Division(int a, int b)
{
    
	// 当b == 0时抛出异常
	if (b == 0)
	{
    
		throw "Division by zero condition!";
	}
	return (double)a / (double)b;
}

void Func()
{
    
	// 这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放.
	// 所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再
	// 重新抛出去.
	int* array = new int[10];
	int len, time;
	cin >> len >> time;

	try
	{
    
		cout << Division(len, time) << endl;
	}
	catch (...)  // 拦截异常,不是要处理异常,Instead, release resources normally
	{
    
		cout << "delete []" << array << endl;
		delete[] array;
		throw;  // Rethrow whatever object is caught
	}

	cout << "delete []" << array << endl;
	delete[] array;
}

int main()
{
    
	try
	{
    
		Func();
	}
	catch (const char* errmsg)
	{
    
		cout << errmsg << endl;
		// 记录日志
	}

	return 0;
}

自定义异常体系

  • 服务器开发中通常使用的异常继承体系
// 服务器开发中通常使用的异常继承体系
class Exception
{
    
public:
	Exception(const string& errmsg, int id)
		:_errmsg(errmsg)
		, _id(id)
	{
    }

	virtual string what() const
	{
    
		return _errmsg;
	}
protected:
	string _errmsg;
	int _id;
};

class SqlException : public Exception
{
    
public:
	SqlException(const string& errmsg, int id, const string& sql)
		:Exception(errmsg, id)
		, _sql(sql)
	{
    }

	virtual string what() const
	{
    
		string str = "SqlException:";
		str += _errmsg;
		str += "->";
		str += _sql;

		return str;
	}

private:
	const string _sql;
};

class CacheException : public Exception
{
    
public:
	CacheException(const string& errmsg, int id)
		:Exception(errmsg, id)
	{
    }

	virtual string what() const
	{
    
		string str = "CacheException:";
		str += _errmsg;
		return str;
	}
};

class HttpServerException : public Exception
{
    
public:
	HttpServerException(const string& errmsg, int id, const string& type)
		:Exception(errmsg, id)
		, _type(type)
	{
    }

	virtual string what() const
	{
    
		string str = "HttpServerException:";
		str += _type;
		str += ":";
		str += _errmsg;

		return str;
	}

private:
	const string _type;
};

void SQLMgr()
{
    
	srand(time(0));
	if (rand() % 7 == 0)
	{
    
		throw SqlException("权限不足", 100, "select * from name = '张三'");
	}

	//throw "xxxxxx";
}

void CacheMgr()
{
    
	srand(time(0));
	if (rand() % 5 == 0)
	{
    
		throw CacheException("权限不足", 100);
	}
	else if (rand() % 6 == 0)
	{
    
		throw CacheException("数据不存在", 101);
	}

	SQLMgr();
}

void HttpServer()
{
    
	// ...
	srand(time(0));
	if (rand() % 3 == 0)
	{
    
		throw HttpServerException("请求资源不存在", 100, "get");
	}
	else if (rand() % 4 == 0)
	{
    
		throw HttpServerException("权限不足", 101, "post");
	}

	CacheMgr();
}

void ServerStart()
{
    
	while (1)
	{
    
		this_thread::sleep_for(chrono::seconds(1));

		try {
    
			HttpServer();
		}
		catch (const Exception& e) // 这里捕获父类对象就可以
		{
    
			// 多态
			cout << e.what() << endl;
		}
		catch (...)
		{
    
			cout << "Unkown Exception" << endl;
		}
	}
}

int main()
{
    
	ServerStart();

	return 0;
}

在这里插入图片描述

异常安全

  • Better not to throw in the constructor ->Objects may be incomplete or not fully initialized
  • Better not to throw in the destructor ->可能导致资源泄漏(内存泄漏,句柄未关闭等)
    在这里插入图片描述

异常规范

  • thow ()If there is an exception type in it,Then that's where the function might throwi有类型
  • 函数后面跟throw() ,The brackets are empty,表示函数不抛异常,但在C++11中更喜欢用noexcept
  • No interface description,Then the description can throw any exception
  • However, it may not be standard in practice,It is difficult to implement in practice,It is also possible that someone wrote it but secretly throws an exception
    在这里插入图片描述
    在这里插入图片描述

异常的优缺点(考点)

优点:

  • Accurately display the wrong kinds of information,better positioningbug
  • The call chain is deep,It's hard for the outermost layer to get errors
  • Third-party libraries need to use exceptions
  • Some classic functions cannot use error codes(For example, it will return a value itself)
    在这里插入图片描述
    缺点:
  • Perform flow hopping,Like the previous recommendation to use sparinglygoto(重要)
  • 有一定的性能开销,但可以忽略不计(Previously returned an error code,Now returns an object,There is also stack overhead)(不是很重要)
  • 没有垃圾回收机制,learning costs ->RAII->Only smart pointers,lock_guard (很重要)
  • C++The exception system is not well defined(不是很重要)
    在这里插入图片描述

总的来说,利大于弊 ,OO
在这里插入图片描述

原网站

版权声明
本文为[GracefulBlack]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208102102164272.html