目录

1.C语言传统的处理错误的方式

2.C++异常概念

3.异常的用法

3.1. 异常的抛出和捕获

3.2. 异常的重新抛出 

3.3. 异常安全

3.4. 异常规范

4. 自定义异常体系

5.标准库异常体系

6.异常的优缺点


1.C语言传统的处理错误的方式

2.C++异常概念

int main()
{
	try
	{
		//要捕获异常的区域
	}
	catch (const Exception& e1)
	{
		// catch()块
	}
	catch (const Exception& e2)
	{
		// catch()块
	}
	catch (const Exception& e3)
	{
		// catch()块
	}
    // ...
	return 0;
}

3.异常的用法

3.1. 异常的抛出和捕获

double Division(double left, double right)
{
	if (right == 0)
	{
        // 当right为0时,会抛出异常
		throw "this is a error except 0";   
	}
	else
	{
		return left / right;
	}
}

void Func1(void)
{
	double x, y;
	std::cin >> x >> y;
	std::cout << Division(x, y) << std::endl;
}

int main()
{
	while (1)
	{
		try
		{
			Func1();
		}
		catch (const char *error_str)
		{
			std::cout << error_str << std::endl;
		}
	}
	return 0;
}

C++异常-LMLPHP

double Division(double left, double right)
{
	if (right == 0)
		throw "this is a error except 0";
	else
		return left / right;
}

void Func1(void)
{
	double x, y;
	std::cin >> x >> y;
	try
	{
		std::cout << Division(x, y) << std::endl;
	}
	catch (const char* error_msg)
	{
		std::cout << error_msg << std::endl;
	}

}

int main()
{
	while (1)
	{
		try
		{
			Func1();
		}
		catch (const char *error_str)
		{
			std::cout << error_str << std::endl;
		}
	}
	return 0;
}

C++异常-LMLPHP

C++异常-LMLPHP

C++异常-LMLPHP

C++异常-LMLPHP

// 由于异常可以随便抛,如果不规范抛异常,那么很有可能出现
// 无法匹配的异常,因此这里的catch为了防止出现这种问题(可以捕获任意类型的异常)
// 一般情况这个catch语句放在最后,防止一些异常没有被捕获,进程crash
// 增强代码的健壮性
catch (...)
{
	std::cout << "Unknown error" << std::endl;
}
namespace Xq
{
	class exception
	{
	public:
		exception(const std::string& error_msg, int error_id)
		:_error_msg(error_msg)
		, _error_id(error_id)
		{}

		const std::string& get_msg() const
		{
			return _error_msg;
		}

		const int get_id() const
		{
			return _error_id;
		}
	private:
		std::string _error_msg;
		int _error_id;
	};

	double Division(double left, double right)
	{
		if (right == 0)
		{
			throw(exception("this a error of except 0", 1));
		}
		else
			return left / right;
	}
	
	void Func1(void)
	{
		double x, y;
		std::cin >> x >> y;
		std::cout << Division(x, y) << std::endl;
	}
}

int main()
{
	while (1)
	{
		try
		{
			Xq::Func1();
		}
		catch (const Xq::exception& e)
		{
			std::cout << "error code:> " << e.get_id() << std::endl;
			std::cout << "error msg:> " << e.get_msg() << std::endl;
		}
		catch (...)
		{
			std::cout << "Unknown error" << std::endl;
		}
	}
	return 0;
}

3.2. 异常的重新抛出 

double Division(double left, double right)
{
	if (right == 0)
		throw "this is a error except 0";
	else 
		return left / right;
}

void Func1(void)
{
	int* arr = new int[10];
	double x, y;
	std::cin >> x >> y;
	std::cout << Division(x, y) << std::endl;

	std::cout << "delete[] " << arr << std::endl;
    delete[] arr;
}

int main()
{
	while (1)
	{
		try
		{
			Func1();
		}
		catch (const char *error_str)
		{
			std::cout << error_str << std::endl;
		}
		catch (...)
		{
			std::cout << "Unknown error" << std::endl;
		}
	}
	return 0;
}
void Func1(void)
{
	int* arr = new int[10];
	double x, y;
	std::cin >> x >> y;
	try
	{
		std::cout << Division(x, y) << std::endl;
	}
	catch (const char* str)
	{
		std::cout << "delete[] " << arr << std::endl;
		delete[] arr;

		// 重新抛出异常
        // 可以只使用 throw; 重新抛出当前异常
        //throw;
        //  或者使用 throw str; 重新抛出复制的异常对象
		throw str;
	}

	std::cout << "delete[] " << arr << std::endl;
	delete[] arr;
}
double Division(double left, double right)
{
	if (right == 0)
		throw "this is a error except 0";
	// 假设此时分母为1,也抛异常
	else if (right == 1)
		throw 1;
	else
		return left / right;
}
void Func1(void)
{
	int* arr = new int[10];
	double x, y;
	std::cin >> x >> y;
	try
	{
		std::cout << Division(x, y) << std::endl;
	}
	catch (const char* str)
	{
		std::cout << "delete[] " << arr << std::endl;
		delete[] arr;
		// 重新抛出异常
		throw;
	}
    // 捕获未匹配的异常类型
	catch (...)
	{
		std::cout << "delete[] " << arr << std::endl;
		delete[] arr;
		// 重新抛出异常
		throw;
	}

	std::cout << "delete[] " << arr << std::endl;
	delete[] arr;
}

3.3. 异常安全

3.4. 异常规范

// C++98:
// 注意: 这里的异常声明并不是必须的,比较繁琐,
// 实际中很多人没有去遵守规范,形同虚设

// 表示这个函数不会抛异常
void func1() throw();
// 表示这个函数可能会抛出type1或type2或type3的异常
void func2() throw(type1, type2, type3);
// 这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 这里表示这个函数不会抛出异常
void* operator delete (std::size_t size, void* ptr) throw();

// C++11:
// 如果一个函数明确了不抛异常,那么加noexcept
void func3() noexcept;
// 如果一个函数可能会抛异常,什么都不加
void func4();

// 在这里经测试发现, 如果一个函数被noexcept声明了,但实际上却抛异常了
// 编译器会报警告,但没有报错
// 而如果此时捕获异常就会导致进程崩溃

4. 自定义异常体系

namespace Xq
{
	class exception
	{
	public:
		exception(const std::string& error_msg, int error_id)
			:_error_msg(error_msg)
			, _error_id(error_id)
		{}
        // 在这里为了构成多态
		virtual const std::string what() const
		{
			return _error_msg;
		}
		const int get_id() const
		{
			return _error_id;
		}
	protected:
		const std::string _error_msg;
		int _error_id;
	};

	class sql_exception : public exception
	{
	public:
		sql_exception(const std::string& error_msg, int error_id, const std::string sql)
			:exception(error_msg, error_id)
			, _sql(sql)
			{}

		virtual const std::string what() const
		{
			std::string ret = "sql_exception:";
			ret += _error_msg;
			ret += ": ";
			ret += _sql;
			return ret;
		}
	private:
		const std::string _sql;
	};

	class cache_exception : public exception
	{
	public:
		cache_exception(const std::string& error_msg, int error_id)
			:exception(error_msg, error_id)
			{}

		virtual const std::string what() const
		{
			std::string ret = "cache_exception: ";
			ret += _error_msg;
			return ret;
		}
	};

	class http_exception : public exception
	{
	public:
		http_exception(const std::string& error_msg, int error_id, const std::string& type)
			:exception(error_msg, error_id)
			, _type(type)
		{}

		virtual const std::string what() const
		{
			std::string ret = "http_exception: ";
			ret += _error_msg;
			ret += ": ";
			ret += _type;
			return ret;
		}
	private:
		const std::string _type;
	};

	void sql_mgr(void)
	{
		if (rand() % 2 == 0)
		{
            // 抛子类对象,父类对象去捕捉,构成多态
			throw sql_exception("没有权限", 5, "select * from name = 李四");
		}
	}

	void cache_mgr(void)
	{
		if (rand() % 3 == 0)
		{
            // 抛子类对象,父类对象去捕捉,构成多态
			throw cache_exception("没有权限", 10);
		}
		else if (rand() % 4 == 0)
		{
            // 抛子类对象,父类对象去捕捉,构成多态
			throw cache_exception("没有该数据", 11);
		}
		sql_mgr();
	}

	void http_serve(void)
	{
		if (rand() % 5 == 0)
		{
            // 抛子类对象,父类对象去捕捉,构成多态
			throw http_exception("请求资源不存在", 20, "pos");
		}
		cache_mgr();
	}
}

int main()
{
	srand((unsigned int)time(nullptr));
	while (1)
	{
		try
		{
			Sleep(1000);
			Xq::http_serve();
		}
		catch (const Xq::exception& e)
		{
			std::cout << e.what() << std::endl;
		}
		catch (...)
		{
			std::cout << "Unknown error" << std::endl;
		}
	}
	return 0;
}

5.标准库异常体系

C++异常-LMLPHP 

C++异常-LMLPHP 

6.异常的优缺点

10-15 21:50