-- 侃侃而谈,try-throw-catch的好处有哪些?
## 背景
涉及文章说明内容的完整示例代码,可以参见存在github。
## 背景
既然C++语法久以来就一直存在着针对异常处理支持,即try-throw-catch结构,那么该异常处理就有一定的实用之处,虽说在C++业界有众多的程序员们对此不断地批判着,其中也不乏大牛们。所以,我在此谈及其好处,一定有很多人表示抗议。抗议的暂且淡定,继续看看下面内容,同时欢迎指正。
## 观点
先说说我个人针对C++异常try-throw-catch结构的认识过程吧(至今),如下:
首先,刚开始从C过来学习C++时,语法上提供这样异常机制对于新手的我,简直耳目一新。
-- 慕之敬之
然后,随着多年慢慢学习C++过程中,不断看到诸多对其批判与鄙视,而且其中不乏大牛们。
-- 斥之远之
最后(至今),鉴于最近工作内容涉及的重构代码--剔除很多的异常逻辑,我“深深”发现try-throw-catch结构的异常机制针对复杂的错误情况处理,颇显便捷与实用的益处。
-- 思之慎之
(PS. 以下内容表示看好C++异常处理,违背了多数程序员的观点,望轻拍。
其实,个人还保持比较反对C++异常处理的态度,以后照样慎用!)
## 示例
以简单代码的例子说说,其便捷与实用之处。如下:
const unsigned BUFFER_MAX_LEN = 64;
void read_file_e(FILE* f, char* buf, size_t buf_size)
{
if (NULL == f)
throw std::logic_error("f is NULL.");
// ... read file ....
}
bool read_file_r(FILE* f, char* buf, size_t buf_size)
{
if (NULL == f)
return false;
// ... read file ....
return true;
}
class read_info_class
{
public:
enum { ITEM_COUNT = 30, INFO_MAX_LEN = BUFFER_MAX_LEN };
public:
read_info_class()
: _file(0) {}
read_info_class(FILE* file)
: _file(file) {}
~read_info_class()
{
if (_file)
fclose(_file);
}
void set_file (FILE* new_f)
{
if (_file)
fclose(_file);
_file = new_f;
}
void read_info_for_item1_e()
{
//assert (_file);
string info;
info.resize(INFO_MAX_LEN);
read_file_e(_file, const_cast<char*>(info.c_str()), info.size());
_info_items.push_back(info);
read_file_e(_file, const_cast<char*>(info.c_str()), info.size());
_info_items.push_back(info);
// ... if read more items than 30...
}
void read_info_for_item2_e()
{
/* ... */
}
void read_info_for_item3_e()
{
/* ... */
}
void read_info_for_item4_e()
{
/* ... */
}
void read_info_for_item5_e()
{
/* ... */
}
// ... more ...
bool read_info_for_item1_r()
{
//assert (_file);
string info;
info.resize(INFO_MAX_LEN);
if (!read_file_r(_file, const_cast<char*>(info.c_str()), info.size()))
return false;
_info_items.push_back(info);
if (!read_file_r(_file, const_cast<char*>(info.c_str()), info.size()))
return false;
_info_items.push_back(info);
// ... if read more items than 30...
return true;
}
bool read_info_for_item2_r()
{
/* ... */ return true;
}
bool read_info_for_item3_r()
{
/* ... */ return true;
}
bool read_info_for_item4_r()
{
/* ... */ return true;
}
bool read_info_for_item5_r()
{
/* ... */ return true;
}
// ... more ...
private:
FILE* _file;
vector<string> _info_items;
// more other var...
};
void do_read_func_e()
{
// do something ...
FILE* file = NULL;
// open file and ...
vector<char> buf(BUFFER_MAX_LEN);
read_file_e(file, &buf[0], buf.size());
// handle buf's data ...
read_file_e(file, &buf[0], buf.size());
// more ...
read_info_class read_info;
// initialize read_info and ...
read_info.read_info_for_item1_e();
read_info.read_info_for_item2_e();
read_info.read_info_for_item3_e();
read_info.read_info_for_item4_e();
read_info.read_info_for_item5_e();
// more read_info_for_item5_e ...
return;
}
bool do_read_func_r()
{
// do something ...
FILE* file = NULL;
// open file and ...
vector<char> buf(BUFFER_MAX_LEN);
if (!read_file_r(file, &buf[0], buf.size()))
return false;
// handle buf's data ...
if (!read_file_r(file, &buf[0], buf.size()))
return false;
// more ...
read_info_class read_info;
// initialize read_info and ...
if (!read_info.read_info_for_item1_r() ||
!read_info.read_info_for_item2_r() ||
!read_info.read_info_for_item3_r() ||
!read_info.read_info_for_item4_r() ||
!read_info.read_info_for_item5_r() ) /// || more read_info_for_item*_r ...
return false;
// ...
return true;
}
void test_read_func_e()
{
// ...
try
{
do_read_func_e();
}
catch (std::exception& e)
{ // 里边一个throw操作,就直接到了错误处理地方了,很快吧^_^
std::cerr << " catch error:" << e.what() << endl;
}
// ... more ...
}
void test_read_func_r()
{
if (!do_read_func_r())
{ // 经过了一系列的if-return判断,最后终于到了错误处理地方了,不容易啊- -!
std::cerr << " occur error from do_read_func_r." << endl;
}
}
## 总结
综上示例,稍微总结一下,try-throw-catch结构的C++异常处理机制的优势地方:
1. 便于集中处理不同的异常情况,尤其针对不同(多)逻辑层次的异常处理情况,但最好不要跨模块处理异常。
针对不同(多)逻辑层次的异常处理,若不使用异常处理机制,则需要在错误(异常)出现地方地方一层层返回错误情况,直到得到处理,编写代码时负担累赘比较大。
2. 针对异常处理情况,其可扩展性比较好。
如增加或减少一种异常的处理情况,涉及代码逻辑的修改比较小,只要取消最初的throw和catch处理对应情况。
3. 当发现错误情况,throw可立即中止该下面逻辑的执行,直至找到对应的catch情况,否则程序崩溃。
既是优点也是缺点。
4. 免去手动编写很多的if-return逻辑,否则严重影响代码逻辑的清晰与美观,尤其对于那些具有代码洁癖的程序员。
5. 建议:在不影响程序运行性能的情况下,可考虑使用异常处理,尤其程序存在复杂的错误(异常)处理情况的。
也就是说,复杂的错误处理逻辑,不是程序主要逻辑,即使使用了C++异常处理也不影响程序的整体性能。
## 猜想
猜想,但未进一步验证:
C++异常机制的实现涉及到相应操作系统的异常处理机制,编译器自动转换为系统的异常处理逻辑,当然这里的转换逻辑一定很复杂。
以windows为例,C++异常处理的底层实现可能将涉及 SEH(结构化异常处理):
__try{}__except(…){}
__try{}__finally{}
__try{}__finally{}
还有,涉及系统函数UnHandleExceptionFilter,SetUnHandleExceptionFilter (详见《软件调试》)...
PS. 至于Linux系统下,C++异常处理的底层实现日后有机会再考究。
## 附:
涉及文章说明内容的完整示例代码,可以参见存在github。
没有评论:
发表评论